Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
SVEUCILIŠTE U ZAGREBUFAKULTET ELEKTROTEHNIKE I RACUNARSTVA
ZAVRŠNI RAD br 5150
Izrada digitalnih 3D igara urazvojnoj okolini Unity
Dobrila Šunde
Zagreb lipanj 2017
Umjesto ove stranice umetnite izvornik Vašeg rada
Da bi ste uklonili ovu stranicu obrišite naredbu izvornik
Zahvala Nikoli Vuckovicu zbog velike pomoci sa izradom blend modela
iii
SADRŽAJ
1 Uvod 1
2 Postavljanje pocetne scene 221 Instalacija 2
22 Kreiranje prve scene 2
23 Razvojna okolina Unity 3
24 Konzola 4
25 Programski jezik 4
3 Unos glavnog lika u scenu 731 Skaliranje 7
32 Kreiranje osnovnih objekata 7
33 Unos Blender modela u Unity i pocetni problemi 8
4 Kamera 1241 Perspektivna i ortografska kamera 12
42 Pogled iz prvog lica u pogled iznad glave 13
43 Fiksirana kamera 15
44 Bacanje zraka (engl Ray casting) 16
5 Kretanje 1951 Navigacijski sustav u Unityu 19
52 Pronalazak puta 20
53 Kreiranje navigacijskog sustava 21
54 Programiranje kretanja 22
6 Korisnicko sucelje 3561 Platno 35
62 Osnovne komponente 36
iv
63 Korisnicko sucelje igraca 37
64 Korisnicko sucelje neprijatelja 38
7 Teren 4271 Kreiranje i uredivanje terena 42
72 Visinske mape 42
73 Teksture za teren 44
8 Zakljucak 46
9 Zasluge 47
Literatura 48
v
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Umjesto ove stranice umetnite izvornik Vašeg rada
Da bi ste uklonili ovu stranicu obrišite naredbu izvornik
Zahvala Nikoli Vuckovicu zbog velike pomoci sa izradom blend modela
iii
SADRŽAJ
1 Uvod 1
2 Postavljanje pocetne scene 221 Instalacija 2
22 Kreiranje prve scene 2
23 Razvojna okolina Unity 3
24 Konzola 4
25 Programski jezik 4
3 Unos glavnog lika u scenu 731 Skaliranje 7
32 Kreiranje osnovnih objekata 7
33 Unos Blender modela u Unity i pocetni problemi 8
4 Kamera 1241 Perspektivna i ortografska kamera 12
42 Pogled iz prvog lica u pogled iznad glave 13
43 Fiksirana kamera 15
44 Bacanje zraka (engl Ray casting) 16
5 Kretanje 1951 Navigacijski sustav u Unityu 19
52 Pronalazak puta 20
53 Kreiranje navigacijskog sustava 21
54 Programiranje kretanja 22
6 Korisnicko sucelje 3561 Platno 35
62 Osnovne komponente 36
iv
63 Korisnicko sucelje igraca 37
64 Korisnicko sucelje neprijatelja 38
7 Teren 4271 Kreiranje i uredivanje terena 42
72 Visinske mape 42
73 Teksture za teren 44
8 Zakljucak 46
9 Zasluge 47
Literatura 48
v
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Zahvala Nikoli Vuckovicu zbog velike pomoci sa izradom blend modela
iii
SADRŽAJ
1 Uvod 1
2 Postavljanje pocetne scene 221 Instalacija 2
22 Kreiranje prve scene 2
23 Razvojna okolina Unity 3
24 Konzola 4
25 Programski jezik 4
3 Unos glavnog lika u scenu 731 Skaliranje 7
32 Kreiranje osnovnih objekata 7
33 Unos Blender modela u Unity i pocetni problemi 8
4 Kamera 1241 Perspektivna i ortografska kamera 12
42 Pogled iz prvog lica u pogled iznad glave 13
43 Fiksirana kamera 15
44 Bacanje zraka (engl Ray casting) 16
5 Kretanje 1951 Navigacijski sustav u Unityu 19
52 Pronalazak puta 20
53 Kreiranje navigacijskog sustava 21
54 Programiranje kretanja 22
6 Korisnicko sucelje 3561 Platno 35
62 Osnovne komponente 36
iv
63 Korisnicko sucelje igraca 37
64 Korisnicko sucelje neprijatelja 38
7 Teren 4271 Kreiranje i uredivanje terena 42
72 Visinske mape 42
73 Teksture za teren 44
8 Zakljucak 46
9 Zasluge 47
Literatura 48
v
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
SADRŽAJ
1 Uvod 1
2 Postavljanje pocetne scene 221 Instalacija 2
22 Kreiranje prve scene 2
23 Razvojna okolina Unity 3
24 Konzola 4
25 Programski jezik 4
3 Unos glavnog lika u scenu 731 Skaliranje 7
32 Kreiranje osnovnih objekata 7
33 Unos Blender modela u Unity i pocetni problemi 8
4 Kamera 1241 Perspektivna i ortografska kamera 12
42 Pogled iz prvog lica u pogled iznad glave 13
43 Fiksirana kamera 15
44 Bacanje zraka (engl Ray casting) 16
5 Kretanje 1951 Navigacijski sustav u Unityu 19
52 Pronalazak puta 20
53 Kreiranje navigacijskog sustava 21
54 Programiranje kretanja 22
6 Korisnicko sucelje 3561 Platno 35
62 Osnovne komponente 36
iv
63 Korisnicko sucelje igraca 37
64 Korisnicko sucelje neprijatelja 38
7 Teren 4271 Kreiranje i uredivanje terena 42
72 Visinske mape 42
73 Teksture za teren 44
8 Zakljucak 46
9 Zasluge 47
Literatura 48
v
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
63 Korisnicko sucelje igraca 37
64 Korisnicko sucelje neprijatelja 38
7 Teren 4271 Kreiranje i uredivanje terena 42
72 Visinske mape 42
73 Teksture za teren 44
8 Zakljucak 46
9 Zasluge 47
Literatura 48
v
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
1 Uvod
Korištenje Unity razvojne okoline eksponencijalno raste zadnjih par godina Razlog
tomu vjerojatno leži u njegovoj jednostavnosti i poslovnom modelu koji omogucava
besplatno korištenje Unity 5 osobne licence za edukacijske svrhe te za tvrtke s priho-
dima manjim od 100000$ Ono što Unity je i ono što promovira je pojednostavljivanje
svih komponenata potrebnih za razvoj igre No takoder pruža svu slobodu programeru
da dodatno razvije i poboljša njihov sustav u obliku koji njemu najviše odgovara Rad
s animacijama teksturama i modelima je vrlo jednostavan i ne zahtijeva nikakvo zna-
nje programera o njihovom razvoju ili ucitavanju kako bi mogli raditi s njima Tako-
der postoje vec mnogi primjeri programskog koda ponudeni na službenim stranicama
Unitya za dizajnere koji nisu iskusni u programiranju Programski kodovi su odlicno
opisani i rješavaju u par linija teške probleme poput navigacije kamere osvjetljenja
itd Cilj ovog rada je pokazati kako se lako mogu savladati osnove rada u Unityu i
kako iskoristiti naše programersko predznanje dobiveno s dosadašnjim studiranjem za
dodatno poboljšavanje svega što Unity nudi te i za lakše razumijevanje kako vec im-
plementirani algoritmi Unitya funkcioniraju Svako poglavlje predstavlja svojevrsni
zadatak za cije se rješavanje nude razna rješenja i objašnjenje potrebne teorije te na
kraju i opis rješenja koje je iskorišteno u ovom projektu
1
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
2 Postavljanje pocetne scene
U ovom poglavlju je predstavljena instalacija razvojne okoline Unity te kreiranje po-
cetnog projekta u kojem ce se do kraja ovog rada izradivati zamišljena igra Upoznaje
se s radom konzole i odlucuje se koji programski jezik ce biti korišten Opisuje se i
objašnjava rad u razlicitim prozorima razvojne okoline te snalaženje u samoj sceni ra-
zvoja igre Nakon kraja ovog poglavlja želi se imati instaliran Unity i pokrenut prazan
projekt
21 Instalacija
Kao što je vec navedeno Unity je besplatan za korištenje za privatne edukacijske te
opcenito bilo kakve nekomercijalne svrhe Razvojni alat se može skinuti i instalirati sa
službene stranice Instalacija je prilicno jednostavna te ima detaljna uputstva koja se
mogu slijediti Verzija korištena tijekom ostatka ovog rada je Unity 56 Za kodiranje
skripti korišten je Microsoft Visual Studio 2017 Naravno može se koristiti i Mono
Develop koji dolazi skupa s instalacijom Unitya
22 Kreiranje prve scene
Nakon instalacije Unitya kreira se novi projekt kao što se vidi na slici 21 Odabere
se ime projekta te mjesto na disku gdje ce se spremiti Nakon kreiranja projekta otvara
se klasicna pocetna scena koja se sastoji od glavne kamere te usmjerenog svijetla koji
su oznaceni brojem 1 na slici 22 Brojem 2 na slici 22 je oznacen prozor projekt
(engl Project) gdje ce se nalaziti sve skripte objekti materijali i sl koje cemo kreirati
kroz izradu projekta Sve te komponente se zapravo spremaju na disku ovisno o tome
gdje je Unity instaliran i gdje je postavljeno spremanje projekata Npr za ovaj projekt
je korišteno DUnity ProjectsAlice Prazni projekt spremamo koristeci postupak
datoteka (engl File) -gt spremi scenu kao (engl Save Scene As) kako bi se kreirala
prva scena u Unityu Odabire se proizvoljno ime te se klikne spremi (engl Save)
2
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 21 Kreiranje projekta
23 Razvojna okolina Unity
Na slici 22 može se vidjeti ovaj projekt u nekoj kasnijoj fazi rada Koristi se ova slika
za lakše objašnjavanje dijelova razvojne okoline Unity Razlikuju se dva pogleda
pogled scene i pogled igre koji se vide i na slici 22 pod brojem 3 U pogledu scene
ureduje se scena igre dodaju se objekti skripte te sve ostalo što je potrebno Nakon
prebacivanja u pogled igre može se igrati dosad izradena verziju igre to je ono što ce
igrac zapravo vidjeti Na samom vrhu slike 22 oznaceno brojem 4 vidimo tri gumba
kao na slici 23 igraj (engl Play) pauziraj (engl Pause) i korak (engl Step) Ti
gumbi prebacuju pogled u pogled igre Sve promjene koje se naprave nad objektima
u pogledu igre su privremeni te ce se vratiti na staro kada se izade iz tog pogleda
Pritisak na gumb Play automatski prebacuje na prozor igra (engl Game) iz prozora
scena (engl Scene) ciji se nazivi mogu vidjeti ispod tih gumba
Dalje postoje gumbi oznaceni brojem 5 na slici 22 koji pomažu s kretanjem oko scene
i manipulacijom objekata u sceni koji su prikazani na slici 24 Prvi gumb sa slikom
ruke omogucava pomicanje po sceni dok drugi gumb omogucava pomicanje objekata
po sceni Treci gumb služi za rotaciju objekata cetvrti za skaliranje i peti služi za
korisnicko sucelje
3
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 22 Razvojna okolina Unity
Slika 23 Gumbi Pokreni Pauziraj i Korak
24 Konzola
Konzola u Unityu vecinom služi za pomoc pri traženju greški u programskom kodu
Može se vidjeti na slici 22 u donjem dijelu Unitya u obliku kartice pored kartice
Project Ako se ne nalazi tamo mora se dodati odlaskom na prozori (engl Windows)-
gt konzola (engl Console) Pritiskom na nju primjecuje se da je skroz prazna i da
imamo još par kartica ocisti (engl Clear) sruši (engl Collapse) ocisti pri pokretanju
(engl Clear On Play) i pri grešci pauziraj (engl Error Pause) Clear služi za cišce-
nje dosad ispisanih poruka Obicno se oznacava Clear On Play da uvijek ocisti stare
poruke te da svaki put kad se pokrene igra dobiju nove Collapse pomaže ako postoji
puno istih poruka npr je korištena while petlja i ceka se neka promjenu u sceni Nije
potrebno da se ispisuje poruka Cekam cijelo vrijeme dok se ceka nego samo jednom
25 Programski jezik
Unity podržava C i Javascript programske jezike te je kroz projekt korišten samo C
Pretpostavlja se da je citatelj upoznat barem sa sintaksom C-a te osnovama objektno
4
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 24 Alati za transformaciju
orijentiranog programiranja Nije potrebno veliko znanje C-a kako bi se kodiralo u
Unityu potrebno je samo razumjeti kako se radi s objektima te poznavati sintaksu C-
a zbog rada s razlicitim vrstama varijabli (za razliku od Python-a gdje nije potrebno
specificirati je li varijabla cijeli broj decimalni broj itd) Unutar prozora oznacenim
brojem 2 na slici 22 stisne se desni klik i odabere kreiraj (engl Create) i C skripta
(engl C Script) da se doda nova skripta Duplim klikom na novo-kreiranu skriptu
otvara se Microsoft Visual Studio ili neka druga razvojna okolina koja podržava C u
kojem se sad može pisati programski kod Programski kod 21 je primjer ispisivanja
jednostavne poruke u konzoli
Programski kod 21 HelloWorld1cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
print(Hello World)
Update se zove svaki okvir (engl Frame)
void Update ()
Sada kada se pritisne na gumb Play sa slike 23 može se vidjeti ispis u konzoli Hello
world Još jedan nacin ispisivanja u konzolu je prikazan programskim kodom 22
Programski kod 22 HelloWorld2cs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
5
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
public class HelloWorld MonoBehaviour
koristi se za inicijalizaciju
void Start ()
DebugLog(Hello world)
Update se zove svaki okvir (engl Frame)
void Update ()
Ne postoji nikakva bitne razlika izmedu ta dva nacina pa se koristi bilo koji
6
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
3 Unos glavnog lika u scenu
U ovom poglavlju opisuju se neki pocetni problemi s kojima se susrece pri ubacivanju
modela iz popularnog programa za modeliranje Blender Objašnjavaju se i modeli koji
su ponudeni unutar samog Unitya poput kocke i neke osnovne njihove transformacije
Nakon kraja ovog poglavlja želi se imati svojevrsno tlo i ubaceni glavni lik skupa s
njegovim teksturama i animacijama iz Blender-a koji nece propadati kroz tlo
31 Skaliranje
Jedno od osnovnih stvari o kojima se razmišlja prilikom kreiranja igre je koja ce se
brojcana skala koristiti Unity ima svoje mjerne jedinice koji predstavljaju metre u
njegovom fizickom sustavu Ovisno o tipu igre koja se kreira mora se paziti na skali-
ranje Izraduje li se neka igru u svemiru nece se koristiti naše realne mjerne jedinice
nego ce ih se naravno skalirati U ovom slucaju kreira se RPG (Role-playing game)
igra gdje nam je glavni lik covjek te ce se koristiti normalne Unity mjerne jedinice bez
skaliranja
32 Kreiranje osnovnih objekata
Za pocetak potrebno je kreirati jednostavno tlo Kocka se kreira s objekt igre (engl Ga-
meObject) -gt 3D objekt (engl 3D Object) -gt kocka (engl Cube) te se dobiva rezultat
kao na slici 31 Zasad se kocka skalira po x i z osi sa 100 Tlo je uobicajeno zelene
boje pa mu se dodaje novi materijal Pritisne se u prozor imovina (engl Asset) desnim
klikom miša i odabere se kreiraj (engl Create) -gt materijal (engl Material) kao što se
može vidjeti na slici 32 Klikom na novo-stvoreni materijal desno se pojavljuje novi
prozor Inspektor (engl Inspector) gdje se može odabrati boja Nakon toga samo se
povuce lijevim klikom miša materijal na skaliranu kocku tj tlo S obzirom na to
kako se želi da ta skalirana kocka glumi tlo želi se takoder da se i ostali objekti nalaze
7
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 31 Kreiranje tla
na njoj Zato ce se tlo morati pomaknuti po y osi za -05 kako bi se olakšalo daljnje
dodavanje objekata
33 Unos Blender modela u Unity i pocetni problemi
Krece se s ubacivanjem svog lika u igru Lik koji se koristi kroz ostatak ovog rada na-
pravljen je u programu Blender koji služi za 3D modeliranje blend objekt se može
samo povuci mišem u Unity iz datoteke u kojoj se nalazi
1 problem Kada se blend datoteka ubacuje u Unity on nece automatski ubaciti i
teksture koje su korištene u izradi tog modela Najlakši nacin bi bio izrada nove dato-
teku unutar Assets datoteke u Unityu i ubacivanje i blend modela i teksture koja je bila
korištena u izradi u tu novu datoteku Nakon toga klikom na model unutar prozora In-
spector pod Materials odabire se opcija od modelovih materijala (engl From Modelrsquos
Material) kao na slici33 kako bi Unity ucitavao korištene teksture Ponekad na žalost
ni to ne funkcionira pa ce se ovdje objasniti još jedan malo opcenitiji pristup Pri unosu
blend modela Unity kreira novu datoteku i nazove ju materijali (engl Materals) Ako
se dogodi da se korištene teksture na modelu ne vide treba se pogledati u tu datoteku
U njoj ce se nalaziti prazni materijali s istim imenima korištenih tekstura kao npr u
slucaju ovog projekta drvo (engl Wood) Tada se mora odabrati u desnom prozoru
materijala albedo (engl Albedo) kao na slici 34 i u ponudenim Assets naci teksturu
koja je korištena (u ovom slucaju Wood)
8
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 32 Kreiranje materijala
2 problem Sada kada je lik pozicioniran u ishodištu (x = 0 y = 0 z = 0) može se
dogoditi da se ne nalazi tocno na tlu koje je kreirano To dakako ovisi o modeliranju
koordinatama koje su korištene i skaliranju pri izradi modela Lik korišten u ovom
radu mora se pomaknuti na koordinatu x = 0 y = 15 z = 0 kako bi stajao tocno na tlu
3 problem Kada bi se igra sad pokrenula pritiskom na gumb Play pri vrhu Unitya
lik bi propao kroz tlo Zašto se to dogada Zbog necega što se zove sudarac (engl Col-
lider) u Unityu koji ce kasnije biti pomnije objašnjen Za sada se samo žele postaviti
neke pocetne stvari kako bi bilo lakše testirati osnovnu interakciju lika i objekata u
prostoru U desnom prozoru Inspector kada je lik oznacen vidi se opcija dodaj kom-
ponentu (engl Add Component) Stisne se na to i upiše sudarac u obliku kapsule
(engl Capsule Collider) kako bi se dodao novi sudarac To je zapravo samo sudarac
9
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 33 Unos blend modela u scenu
koji je u obliku kapsule te se igrajuci nekim njegovim osnovnim opcijama može na-
mjestiti vanjski oblik lika Dodaje se još jedna komponenta nad likom Ponovno se
stisne na Add Component te upiše kruto tijelo (engl Rigid Body) što ce takoder biti
naknadno objašnjeno Zasad je bitno razumijevanje da to omogucava liku da se ponaša
kao kruto tijelo u prostoru
4 problem Sada bi kada se igra pokrene trebao postojati lik koji ne propada kroz tlo
Naravno kao najosnovniju mehaniku želi se mogucnost kretanja po tom tlu Skripta
koja se treba napraviti kako bi se lik kretao po tlu nije zapravo komplicirana Sastoji
se samo od toga da se prilikom pritiska na odredeno slovo tipkovnice objekt translatira
po prostoru No ovaj model takoder sadrži i animacije za hodanje te se želi i to ukom-
ponirati Zato ce se takoder sada spomenuti još jedna nova komponenta kontrolor
animacija (engl Animator Controller) Dodaje se i ta komponenta na lika i prebacuje
se na prozor animator (engl Animator) koji se vidi na slici 35
U ovom prozoru postoji par novih opcija Mogu se dodavati nova stanja u kojima
ce se lik naci ovisno o nekim uvjetima koji se zadaju Pocetno stanje je ulazno stanje
(engl Entry State) i iz njega se želi da se lik nade u stanju mirovanja Stisne se desni
klik miša i odabere se novo stanje (engl New State) U ovom projektu je nazvano
Mirovanje Iz mirovanja ovisno o tome kada osoba pritisne neku tipku tipkovnice
želi se da se lik krene kretati Zato treba dodati novo stanje Hodanje Doda se
novo stanje istim postupkom kao i prvo Sada se naravno moraju dodati i usmjereni
prijelazi Stisne se desni klik miša na Mirovanje i odabere dodaj prijelaz (engl Add
10
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 34 Traženje tekstura Vašeg blend modela
Slika 35 Animator
Transition) To je sada kreiralo usmjerenu strelicu koja se može povuci prema Ho-
danje Isto to se napravi i u suprotnom smjeru Desni klik miša na Hodanje Add
Transition i povuce se strelica prema Mirovanje Naravno moraju se dodati uvjeti
koji ce odredivati kada ce objekt prijeci iz jednog stanja u drugo U ovom slucaju je
korišten cijeli broj (engl Integer) Ostatak problema kretanja rješavat ce se u poglavlju
4 Bacanje zraka i kretanje po mapi s mišem
11
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
4 Kamera
U ovom poglavlju se postavlja i bira prava kamera za igru Tijekom izrade igre treba se
takoder razmišljati i iz kojeg kuta ce se imati pogled na nju te hoce li se kamera pomi-
cati s kretanjem lika hoce li se moci rotirati itd Pri kreiranju 3D igre u pogledu scene
primjecuje se da su svi objekti i transformacije u 3D-prostoru No s obzirom na to da je
zaslon monitora igraca 2-dimenzionalan te se ne može prikazati tijela kao takva mora
se moci prikazati sve te objekte u jednoj ravnini i zadržati dojam 3-dimenzionalnosti
To se u Unityu postiže s kamerom Kamera je objekt koja definira pogled i njegov
smjer u prostoru scene Pozicija kamere definira ocište z os definira smjer gledanja
(gledište) te y os definira vrh ekrana Kamera takoder definira velicinu i oblik dijela
koji možemo vidjeti Kamera nam pokazuje ono što ona vidi Kako se ona rotira
translatira itd prikaz scene ce se takoder jednako transformirati Nakon kraja ovog
poglavlja želi se imati kamera koja ce pratiti kretnje lika i imati pogled na njega odoz-
gora
41 Perspektivna i ortografska kamera
Kamerom se zapravo objekte 3D prostora projicira na ravninu u 2D prostor Projek-
cije su matematicki modeli koji govore na koji nacin treba tocke 3D prostora preslikati
u ravninu u tocke 2D prostora Postoji više vrsta projekcija no Unity koristi dvije or-
tografsku projekciju i perspektivnu projekciju Kod ortografskih projekcija kamera je
okomita na ravninu projekcije dok je perspektivna projekcija bliža našem nacinu gle-
danja objekata Možda je najlakše primijetiti razliku koristeci slike Dakle na slici 41
možemo vidjeti blend model koji je modeliran u Blenderu u ortografskoj projekciji te
na slici 42 isti taj model pod istim kutem samo prebacen u perspektivnu projekciju
[6]
Perspektivna projekcija uvodi dvije tocke ocište i gledište Ocište je tocka u ko-
joj se nalazi promatrac Gledište odreduje smjer prema kojem promatrac gleda U
12
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 41 Ortografska projekcija blend modela
tocki gledišta stvara se ravnina projekcije koja je okomita na spojnicu ocište-gledište
[6] I perspektivna i ortografska kamera imaju granicu do koje mogu vidjeti od svoje
trenutne pozicije Ona je definirana upravo tom ravninom projekcije Tocka gledišta
pripada toj ravnini i ona tipicno postaje ishodište lokalnog dvodimenzijskog koordi-
natnog sustava koji razapinjemo u ravnini projekcije Ta ravnina se još naziva i daleka
ravnina podrezivanja zato što svi objekti koji se nalaze na vecoj udaljenosti od nje se
odrežu te ih kamera ne prikazuje Takoder postoji i ravnina podrezivanja blizu ka-
meri [1] Dio koji se prikazuje se nalazi izmedu te dvije ravnine
42 Pogled iz prvog lica u pogled iznad glave
U igrama se cesto koristi prebacivanje iz jednog u drugi pogled kamere Kako se
to postiže Koristeci veci broj kamera U ovom slucaju obradit ce se samo kratki
primjer kako se prebacivati iz pogleda prvog lica u pogled iznad glave U unity-u je
zadano da jedna kamera pokriva cijeli ekran te se zato samo pogled jedne kamere može
vidjeti u jednom trenutku Kamera koju vidimo je ona koja ima najvecu vrijednost
za svoje svojstvo dubine[1] Zato se želi napraviti skripta koja ce se prebacivati s
jedne kamere na drugu da bi se dobili drukciji pogledi na scenu koja je prikazana
programskim kodom 41
Programski kod 41 PrimjerViseKameracs
13
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 42 Perspektivna projekcija blend modela
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kameraPrvogLica
public Camera kameraIznadGlave
funkcija koja se poziva kada se prebacujemo u pogled iznad
glave
public void prikaziPogledIznadGlave()
kameraPrvogLicaenabled = false gasimo kameru prvog
lica
kameraIznadGlaveenabled = true palimo kameru iznad
glave
funkcija koja se poziva kada se prebacujemo u pogled iz
prvog lica
public void prikaziPogledIzPrvogLica()
kameraPrvogLicaenabled = true palimo kameru prvog
lica
overheadCameraenabled = false gasimo kameru iznad
glave
14
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
43 Fiksirana kamera
U sceni projekta vec postoji glavna kamera (engl Main Camera) koju Unity automat-
ski dodaje u scenu Kako bi ta kamera pratila lika može se samo povuci u lijevom
prozoru hijerarhije u hijerarhiju lika kako bi postala njegovo dijete Tako ce se postici
da kamera stalno prati njegove transformacije (translaciju rotaciju) prilikom pokreta-
nja igre No kako bi se postiglo da kamera ostane uvijek fiksirana te se samo krece s
njime umjesto da se kamera rotira skupa s likom dodaje se novi prazni objekt sa Game
Object -gt kreiraj prazan (engl Create Empty) Njegova pozicija se postavlja na x =
0 y = 0 z = 0 ako vec nije tamo te se postavlja taj prazan objekt kao roditelj glavne
kamere Sada kamera ostaje fiksirana na mjestu te se nece ni kretati s likom Kako bi
se krenula kretati mora se dodati nova skripta na taj prazan objekt koji se odsad u pro-
jektu zove Kamera s obzirom na to da zaista i je roditelj glavne kamere Kako bi se u
skripti lakše locirao objekt igraca oznacava ga se u njegovom polju oznaka (engl Tag)
u desnom prozoru Inspector s igrac (engl Player) kao što se može vidjeti na slici 43
zaokruženo plavom bojom
U programskom kodu se želi napraviti varijabla tipa Game Object kako bi se spremilo
igraca kada ga se pronade Unity takoder ima funkciju FindGameObjectWithTag pa
je onda ostatak koda prilicno intuitivan Kada se igrac pronade pomocu njegove oz-
nake Player prilikom svakog osvježavanja poziciji našeg igraca pridružuje se pozicija
kamere kao što je prikazano programskim kodom 42
Programski kod 42 pratiLikacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class pratiLika MonoBehaviour
GameObject igrac
void Start ()
trazi se objekt putem njegove oznake
igrac = GameObjectFindGameObjectWithTag(Player)
15
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 43 Oznacavanje lika radi lakšeg pronalaska u skripti
void LateUpdate ()
trenutni objekt mijenja svoju poziciju u skladu s
pozicijom objekta oznacenog oznakom Player
transformposition = igractransformposition
44 Bacanje zraka (engl Ray casting)
Perspektivna kamera u Unityu koristi oblik krnje piramide za dio koji prikazuje u pros-
toru Svaka tocka nekog objekta kojeg kamera prikazuje zapravo odgovara liniji u pros-
toru svijeta te je nama samo jedna tocka duž te linije vidljiva na objektu Sve iza te
tocke na liniji je zamraceno Vanjski rubovi objekta su definirani razilazecim linijama
16
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
koje odgovaraju kutevima objekta Kada bi se te linije pratile unazad prema kameri
sve bi na kraju konvergirale u jednu tocku U Unityu se ta tocka nalazi tocno na pozi-
ciji kamere i naziva se centrom perspektive Kut naspram linija koje konvergiraju od
gornjeg i donjeg centra ekrana u centru perspektive se zove vidno polje (engl Field Of
View) Sve što pada izvan tih razilazecih linija na rubovima objekta nece biti vidljivo
kameri uz vec prethodno spomenuta ogranicenja ravnina podrezivanja
U igrama je jako korisno imati matematicku reprezentaciju linije koja predstavlja tocku
u pogledu kamere Unity to omogucava u obliku objekta zrake Zraka uvijek odgo-
vara tocki u pogledu pa klasa Kamera (engl Camera) sadrži dvije korisne funkcije
ScreenPointToRay i ViewportPointToRay Razlika izmedu njih je da ScreenPointToRay
ocekuje tocku s koordinatama piksela dok ViewportPointToRay uzima normalizirane
koordinate (od 0 dolje ili lijevo do 1 gore ili desno) Obje funkcije vracaju zraku
koja se sastoji od tocke ishodišta i vektora koji pokazuje smjer linije od tog ishodišta
Zraka izlazi iz ravnine podrezivanja bliže kameri Najcešce se zrake koriste kako bi ih
bacali u scenu Bacanje zraka pošalje imaginarnu liniju uz zraku od njenog ishodišta
dok ne udari u neki sudarac u sceni Tada vraca informaciju o tocki koju je udarila
u objektu RaycastHit To je vrlo korisno kako bi se locirao objekt ovisno o njegovoj
poziciji na zaslonu npr lociranje kursora prikazano programskim kodom 43
Programski kod 43 lociranjeKursoracs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public Camera kamera
void Start()
RaycastHit udar
u objekt Ray se sprema pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
ako zraka udara u neki objekt spremi u objektUdaren to
mjesto
if (PhysicsRaycast(zraka out udar))
Transform objektUdaren = udartransform
17
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Ponekad je takoder korisno dobiti zraku koja odgovara poziciji na zaslonu te onda
pomicati kameru uz tu zraku Npr želi se dozvoliti igracu da može selektirati objekt
mišem i onda ga povecati dok se objekt nalazi cijelo vrijeme na istoj poziciji na zaslonu
ispod miša prikazano programskim kodom 44 [1]
Programski kod 44 povecavanjeSlikecs
using UnityEngine
using SystemCollections
public class Primjer MonoBehaviour
public bool povecavanje
public float brzinaPovecavanja
public Camera kamera
void Update()
ako netko koristi povecavanje slike (engl Zooming)
if (povecavanje)
u objekt Ray sprema se pozicija misa na ekranu
pretvorena u zraku
Ray zraka = kameraScreenPointToRay(Input
mousePosition)
udaljenost povecavanja ce biti jednaka umnosku
brzine povecavanja vremena i vertikalnog smjera
float udaljenostPovecavanja = brzinaPovecavanja
InputGetAxis(Vertical) TimedeltaTime
pomakni kameru u smjeru kursora misa za udaljenost
povecavanja u koordinatnom sustavu svijeta
kameratransformTranslate(zrakadirection
udaljenostPovecavanja SpaceWorld)
18
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
5 Kretanje
Pronalazak puta je zapravo pokušaj aplikacije na racunalu ili algoritma da nade naj-
kracu rutu izmedu dvije tocke To je recimo prakticna verzija rješavanja labirinta Ni
danas ne postoji optimalan algoritam koji ce u svakom slucaju u nekom realno krat-
kom vremenu naci najkraci put U ovom poglavlju objasnit ce se koje algoritme Unity
koristi za svoj navigacijski sustav Objašnjavat ce se i neki osnovni koncepti i obrasci
potrebni za ubrzavanje cijele ideje dojavljivanja promjena u sceni Bit ce prikazani i
programski kodovi potrebni za implementiranje kretanja mišem iili tipkovnicom Na
kraju ovog poglavlja želi se imati lika koji ce se slobodno kretati po sceni na mjesto
koje se odredi klikom miša i mogucnost prebacivanja na upravljanje tipkovnicom
51 Navigacijski sustav u Unityu
U Unityu je problem pronalaska puta vec riješen s necim što se zove navigacijska
mreža (engl NavMesh) To je navigacijski sustav koji ima svoje algoritme pronala-
ska puta i puno pojednostavljuje programiranje kretanja lika Sastoji se od cetiri di-
jela NavMesh agent navigacijske mreže (engl NavMesh Agent) izvanmrežna pove-
zanost(engl Off - Mesh Link) i prepreka navigacijske mreže(engl NavMesh Obstacle)
NavMesh je podatkovna struktura koja opisuje površine po kojima se može kretati
u igri i omogucava pronalazak put od jedne lokacije do druge Navigacijski sustav
treba svoje podatke kako bi predstavio prohodna podrucja u sceni Prohodna podru-
cja definiraju se kao mjesta gdje agent može stajati i kretati se Prohodno podrucje se
automatski izgraduje iz geometrije u sceni testirajuci sva podrucja gdje bi agent mo-
gao stajati Onda se te lokacije spajaju s površinom na vrhu geometrije Ta površina se
naziva onda NavMesh te je možemo vidjeti na 51 NavMesh tada sprema tu površinu
kao konveksne poligone te informacije koji su poligoni susjedni Komponenta Nav-
Mesh Agent pomaže pri kreiranju likova koji se medusobno izbjegavaju dok se krecu
prema cilju U Unityu se agenti opisuju kao valjci Koriste NavMesh kako bi se kretali
i znali koje objekte moraju zaobici te kako da se medusobno zaobidu Off-Mesh Link
19
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
omogucava dodavanje navigacijskih precaca koji se ne mogu predstaviti kao površina
po kojoj se može hodati npr skakanje preko ograde ili otvaranje vrata prije nego što
se ude u neku prostoriju NavMesh Obstacle opisuje prepreke koje se krecu te koje bi
agenti trebali izbjegavati dok hodaju svijetom npr neke bacve koje se kotrljaju prema
igracu Dok se bacva krece agent ce izracunati put oko nje najbolje što može no nakon
što ona naposljetku stane postat ce dio neprohodnog NavMesha te ce se agenti kretati
oko nje [3]
Slika 51 Prikaz navigacijskog sustava u Unityu
52 Pronalazak puta
Dva glavna problema postoje kod pronalaženja puta kako pronaci destinaciju na ni-
vou na kojem se igrac nalazi te kako se onda tamo pomaknuti Pronalaženje destinacije
uzima u obzir cijelu scenu Pomicanje tamo je dinamicnije u obzir uzima samo smjer
kretanja i kako da sprijeci sudaranje s drugim agentima Da bi se pronašao put izmedu
dvije lokacije prvo se moraju oznaciti pocetna i konacna lokacija njihovim najbližim
poligonima Tada se krece tražiti od pocetne lokacije posjecujuci sve susjedne dok se
ne dode do zadane destinacije Onda se prati unatrag vec posjecene poligone kako bi
se našao konacan niz poligona koji vode od pocetka do kraja Algoritam koji Unity
koristi te se cesto koristi za pronalazak puta naziva se A (A zvjezdica) Taj niz po-
ligona koji opisuje put od pocetka do kraja se naziva hodnik Agent ce doci do svoje
20
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
destinacije tako da se uvijek usmjerava prema sljedecem vidljivom kutu hodnika Ta
logika usmjeravanja uvijek uzima poziciju sljedeceg kuta i ovisno o tome nade željeni
smjer i brzinu potrebnu za dolazak na destinaciju Korištenje brzine po želji progra-
mera bi moglo dovesti do sudara s ostalim agentima Izbjegavanje prepreka takoder
pronalazi svoju novu brzinu koja traži ravnotežu izmedu kretanja prema destinaciji i
sprjecavanja buducih sudara s ostalim agentima i kutevima u navigacijskom sustavu
Nakon usmjeravanja i izbjegavanja prepreka izracuna se konacna brzina Unity ta-
koder uzima u obzir i akceleraciju kako bi simulirao realisticnije kretanje Takoder
treba razumjeti razliku izmedu globalne i lokalne navigacije Globalna navigacija se
koristi za pronalazak hodnika u svijetu Linearna lista poligona koja opisuje taj put je
podatkovna struktura koja se koristi za usmjeravanje te se može lokalno prilagodavati
i mijenjati kako se pozicija agenta mijenja Lokalna navigacija pokušava naci efika-
san nacin kako da se igrac pomakne prema sljedecem kutu bez da se sudari s ostalim
agentima ili objektima koji se krecu [3]
53 Kreiranje navigacijskog sustava
Proces kreiranja NavMesha iz geometrije nivoa se naziva pecenje navigacijske mreže
(engl NavMesh Baking) Skuplja sve terene i mreže objekata koji su oznaceni kao
navigacijski staticko (engl Navigation Static) i onda ih procesira kako bi kreirao navi-
gacijski sustav koji aproksimira prohodne površine nivoa Izgradnja (engl NavMesha)
je vrlo jednostavna Prvo se selektira geometrija koja bi trebala utjecati na navigaciju
tj površine po kojima možemo hodati i prepreke Oznaci se Navigation Static da bi ih
ukljucili u NavMesh Baking proces Prilagode se postavke kako bi odgovarale velicini
agenta - radijus (npr koliko blizu se može doci zidovima) visina (koliko su nisko
prostori koje agent može doseci) maksimalni nagib (koliko su kose rampe po kojima
se agent može uspeti) visina stube(koliko su visoke prepreke na koje agent može za-
koraciti) Onda jednostavno stisnemo ispeci (engl Bake) da izgradimo svoj NavMesh
Izgradeni NavMesh cemo moci vidjeti kao plavu površinu kao na slici 51 te ce se stvo-
riti nova datoteka s nazivom trenutne scene (ako vec ne postoji) i unutra ce se spremiti
kreiran navigacijski sustav [3]
21
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
54 Programiranje kretanja
Na liku se trenutno nalazi par stvari Animator Capsule Collider i Rigid Body Sada
je cilj isprogramirati mogucnost odredivanja gdje ce se lik kretati klikom miša na to
mjesto Dodaje se nova komponenta na lika NavMesh Agent Ta komponenta za-
pravo vec ima svoj sudarac te se slobodno može obrisati Capsule Collider jer postaje
nepotreban Igranjem s opcijama pomak od baze (engl Base Offset) te pod izbjegava-
nje prepreka (engl Obstacle Avoidance) radijus (engl Radius) i visina (engl Height)
prilagodi se sudarac od (engl NavMesh Agent-a) kako bi se obujmilo njime igraca i
sprijecilo propadanje kroz tlo od prije Sada kada postoji komponenta navigacije mora
se dodati skripta koja ce odrediti kada se lik krece te kada se pokrecu njegove anima-
cije iz Animator-a
Da bi se znalo gdje se miš nalazi mora se takoder dodati nova skriptu na kameru Kako
bi se izracunalo gdje trenutno kursor pokazuje Unity koristi vec prethodno spomenuto
bacanje zraka Da bi se moglo koristiti navigaciju putem klika mišem mora se napisati
skripta za glavnu kameru koja ce omoguciti bacanje zraka Skripta BacanjeZraka
dodaje se na objekt Main Camera koja se dodala pod prazni objekt Kamera Ova
skriptu se takoder koristi za razlikovanje raznih vrsta objekata Naime svaki objekt
kao što ima i Tag ima i sloj (engl Layer) Sloj služi kako bi mogli npr razlikovati
neprijatelje od obicnih objekata ili mjesto na koje želimo doci hodanjem Zato cemo
takoder dodati i jednu enumeraciju koja ce nam zasad služiti samo da razlikujemo je li
mjesto prohodno ili ne te jesmo li kliknuli na neprijatelja Kako bi dodali svoje nove
slojeve za objekte moramo kliknuti na Layer i dodaj sloj (engl Add Layer) kao na slici
52 što nas dovodi do novog prozora prikazanog na slici 53
Programski kod 51 bacanjeZrakacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
sluzi za dodavanje novih slojeva u Unity
public enum Sloj
Prohodno = 8
Neprijatelj = 9
KrajSvijeta = -1
22
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 52 Dodavanje novog sloja
public class BacanjeZraka MonoBehaviour
hijerarhija slojeva tj koji ima veci prioritet
public Sloj[] prioritetiSlojeva =
SlojNeprijatelj
SlojProhodno
SlojKrajSvijeta
udaljenost do pozadine je neka izmisljena vrijednost nakon
koje se prestane provjeravati zraka
public float udaljenostDoPozadine = 100f
Camera kamera
RaycastHit _udara
dohvaca varijable ove klase
public RaycastHit udara
get return _udara
Sloj _udaraSloj
23
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 53 Prozor za dodavanje novog sloja
public Sloj udaraSloj
get return _udaraSloj
deklariraj novi tip delegata
public delegate void priPromjeniSloja(Sloj noviSloj)
instanciraj skup promatraca
public event priPromjeniSloja promatraciPromjeneSloja
void Start ()
dohvat glavne kamere
kamera = Cameramain
void Update ()
nadi sloj po prioritetu u koji zraka udara
foreach(Sloj sloj in prioritetiSlojeva)
provjeravamo udara li zraka u neki od slojeva
24
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
var udar = BacanjeZrakaZaSloj(sloj)
if(udarHasValue)
_udara = udarValue
ako se sloj promjenio
if(_udaraSloj = sloj)
spremi novi sloj u varijablu trenutnog sloja
_udaraSloj = sloj
obavijesti promatrace da se sloj promjenio
promatraciPromjeneSloja(sloj)
spremi novi sloj u varijablu trenutnog sloja
ali ne moras obavjestavati promatrace jer je
sloj jednak starom sloju
_udaraSloj = sloj
return
inace vrati da zraka udara u pozadinu i obavijesti
promatrace
_udaradistance = udaljenostDoPozadine
_udaraSloj = SlojKrajSvijeta
promatraciPromjeneSloja(udaraSloj)
RaycastHit BacanjeZrakaZaSloj(Sloj sloj)
kreira se maska za slojeve bit se pomice ulijevo za
onoliko mjesta koliki je redni broj prioriteta sloja
int maska = 1 ltlt (int)sloj
sprema se mjesto pozicije kursora pretvoreno iz tocke u
zraku
Ray zraka = kameraScreenPointToRay(InputmousePosition)
RaycastHit udar
PhysicsRaycast sprema zraku u varijablu tipa
RaycastHit prima jos i maksimalnu udaljenost za koju
provjerava zraku i masku sloja i potom vraca istinu (
engl True) ili laz (engl False) ako je zraka udarila
u sloj
25
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
bool udarioJe = PhysicsRaycast(zraka out udar
udaljenostDoPozadine maska)
ako zraka udara u sloj vrati vrijednost udarca
if(udarioJe)
return udar
return null
U programskom kodu 51 se koristi funkcija za primjenu obrasca promatraca pod
nazivom delegat (engl Delegate) Što je obrazac promatraca (engl Observer) To je
oblikovni obrazac koji se u programiranju koristi
bull kad promjena jednog objekta zahtijeva promjene u drugim objektima koji nisu
unaprijed poznati
bull kad objekt treba obavještavati druge objekte
bull uz uvjet da bude što neovisniji o njima
bull kad je potrebno prikazivati razlicite aspekte nekog dinamickog stanja a želimo
izbjeci ciklicku ovisnost izmedu stanja i pogleda
bull kad postoje dva koncepta jedan ovisan o drugome a zgodno ih je razdvojiti
S obzirom na to da mi samo pri promjeni sloja želimo obavještavati pretplacene pro-
matrace uvodenje delegata nam dosta ubrzava kod Obrazac promatraca funkcionira
tako da glavni objekt igra ulogu izdavaca (izvora informacija) u ovom slucaju to je
glavna kamera Ostali ovisni objekti (promatraci) pretplacuju se kod izdavaca te iz-
davaci obavještavaju pretplatnike o promjenama Promatraci prekidaju pretplatu kad
više ne trebaju obavještavanje Funkcija priPromjeniSloja se definira kao delegat i u
ovom slucaju prima sloj Nakon toga se definira dogadaj (engl Event) tipa tog delegata
(priPromjeniSloja) u ovom slucaju naziva promatraciPromjeneSloja i odsad se unutar
subjekta tim nazivom i poziva Kako bi se neki promatrac pretplatio na informacije
koje izdaje kamera dodaje ove dvije linije koda u svoju skriptu
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
Programski kod 52 služi za kretanje korištenjem NavMesha i lijevog klika miša
26
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Programski kod 52 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
public float dovoljnoBlizu = 01f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora
[SerializeField] float hodajKreciStaniRadijus = 02f
void Start ()
pronadi igraca koji je tipa agenta navigacijskog sustava
(engl NavMeshAgent)
agent = GetComponentltUnityEngineAINavMeshAgentgt()
pronadi prethodno napisanu klasu BacanjeZraka
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
spremi trenutnu poziciju kursora
trenutnaPozicijaKursora = transformposition
void Update()
ako je igrac dosao na zeljeno mjesto zaustavi animaciju
hodanja
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
ako je stisnut lijevi klik misa
if (InputGetMouseButtonDown(0))
ovisno o sloju primjeni akciju
switch(bacanjeZrakaudaraSloj)
ako se po objektu na koji je igrac kliknuo moze
hodati
27
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
case SlojProhodno
spremi u trenutnu poziciju kursora mjesto na
koje je igrac kliknuo
trenutnaPozicijaKursora = bacanjeZrakaudara
point
pokreni animaciju kretanja
GetComponentltAnimatorgt()SetInteger(Move 1)
postavi odrediste agenta na poziciju gdje
je igrac kliknuo misem
agentdestination = trenutnaPozicijaKursora
break
case SlojNeprijatelj
print(Ne mogu hodati prema neprijatelju)
break
default
print(Neocekivani sloj)
return
funkcija za pomoc sa usporavanjem agenta na vrijeme
if (agenthasPath ampamp agentremainingDistance lt
dovoljnoBlizu)
agentdestination = new Vector3(thistransform
positionx agentdestinationy thistransform
positionz)
Takoder želi se dodati novi dizajn kursora pa se povuku psd datoteke koje su prona-
dene na Internetu na stranici Freepik u Unity Kako bi ih Unity doživljavao kao kursore
moraju im se promijeniti teksturu u Kursor (engl Cursor) kao na slici 54 i stisne se
na primijeni (engl Apply)
Programski kod 53 kursorcs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
28
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 54 Dodavanje dizajna kursora
trazi obavezno komponentu BacanjeZraka
[RequireComponent(typeof(BacanjeZraka))]
public class Kursor MonoBehaviour
teksture kursora
[SerializeField] Texture2D kursorZaHodanje = null
[SerializeField] Texture2D kursorZaNapad = null
[SerializeField] Texture2D nepoznatiKursor = null
pomak od gornjeg lijevog kuta teksture koji ce sluziti kao
ciljna tocka
[SerializeField] Vector2 kursorHotspot = new Vector2(0 0)
BacanjeZraka bacanjeZraka
void Start ()
nadi komponentu BacanjeZraka i pretplati se kao promatrac
bacanjeZraka = GetComponentltBacanjeZrakagt()
bacanjeZrakapromatraciPromjeneSloja += priPromjeniSloja
void priPromjeniSloja (Sloj noviSloj)
29
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
ovisno o novom sloju postavi teksturu kursora
switch(noviSloj)
case SlojProhodno
CursorSetCursor(kursorZaHodanje kursorHotspot
CursorModeAuto)
break
case SlojKrajSvijeta
CursorSetCursor(nepoznatiKursor kursorHotspot
CursorModeAuto)
break
case SlojNeprijatelj
CursorSetCursor(kursorZaNapad kursorHotspot
CursorModeAuto)
break
default
DebugLog(Ne znam koji kursor prikazati)
return
Još jedan slucaj kretanja je prikazan programskim kodom 53 Kako programirati
kretanje putem tipkovnice Pa vrlo jednostavno takoder samo i dalje se mora paziti
na pokretanje animacija Konacno mehanika kretanja je riješena programskim kodom
54
Programski kod 54 kretanjecs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
public class Kretanje MonoBehaviour
[SerializeField] float hodajKreciStaniRadijus = 02f
[SerializeField] float napadniKreciStaniRadijus = 5f
UnityEngineAINavMeshAgent agent
BacanjeZraka bacanjeZraka
Vector3 trenutnaPozicijaKursora tockaKlika
bool jeUDirektnomKretanju = false
30
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
float brzina = 50f
float brzinaRotacije = 50f
Use this for initialization
void Start ()
agent = GetComponentltUnityEngineAINavMeshAgentgt()
bacanjeZraka = CameramainGetComponentltBacanjeZrakagt()
trenutnaPozicijaKursora = transformposition
private void FixedUpdate()
stisni G za prebacivanje na upravljanje s tipkovnicom
misem
if(InputGetKeyDown(KeyCodeG))
promjeni tip upravljanja i spremi trenutnu poziciju
kursora
jeUDirektnomKretanju = jeUDirektnomKretanju
trenutnaPozicijaKursora = transformposition
ako se koristi tipkovnica
if (jeUDirektnomKretanju)
ugasi navigacijski sustav i pozovi funkciju kretanja
tipkovnicom
agentResetPath()
ProcesuirajDirektnoKretanje()
else
pozovi funkciju kretanja misem
ProcesuirajKretanjeMisem()
private void ProcesuirajDirektnoKretanje()
ako je pritisnuta tipka W pokreni animaciju kretanja i
pomakni se u smjeru prema naprijed za umnozak brzine i
vremena
31
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
if (InputGetKey(KeyCodeW))
GetComponentltAnimatorgt()SetInteger(Move 1)
thistransformTranslate(Vector3forward Time
deltaTime brzina)
inace ugasi animaciju kretanja
else
GetComponentltAnimatorgt()SetInteger(Move 0)
ako je pritisnuta tipka A rotiraj lika u suprotnom
smjeru kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeA))
thistransformRotate(Vector3up (-1)brzinaRotacije
)
ako je pritisnuta tipka D rotiraj lika u smjeru
kazaljke na satu za brzinu rotacije
if (InputGetKey(KeyCodeD))
thistransformRotate(Vector3up brzinaRotacije)
vec objasnjeno u prijasnjem kodu
private void ProcesuirajKretanjeMisem()
if (agentremainingDistance == 0)
thisGetComponentltAnimatorgt()SetInteger(Move 0)
agentvelocity = Vector3zero
if (InputGetMouseButtonDown(0))
tockaKlika = bacanjeZrakaudarapoint
switch (bacanjeZrakaudaraSloj)
case SlojProhodno
trenutnaPozicijaKursora = SkratiDestinaciju(
32
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
tockaKlika hodajKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
case SlojNeprijatelj
trenutnaPozicijaKursora = SkratiDestinaciju(
tockaKlika napadniKreciStaniRadijus)
GetComponentltAnimatorgt()SetInteger(Move
1)
agentdestination = trenutnaPozicijaKursora
agentspeed = 5f
break
default
print(Neocekivani sloj)
return
funkcija koja sluzi za zaustavljanje agenta prije same
destinacije odredene klikom misem sluzi za implementaciju
napadanja na daljinu
Vector3 SkratiDestinaciju(Vector3 destinacija float
skracenje)
Vector3 vektorRedukcije = (destinacija - transform
position)normalized skracenje
return destinacija - vektorRedukcije
funkcija za crtanje gizmoa
private void OnDrawGizmos()
Gizmoscolor = Colorblack
GizmosDrawLine(transformposition
trenutnaPozicijaKursora)
GizmosDrawSphere(trenutnaPozicijaKursora 01f)
GizmosDrawSphere(tockaKlika 015f)
napadanje na daljinu
33
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Gizmoscolor = new Color(255f 0f 0 5f)
GizmosDrawWireSphere(transformposition
napadniKreciStaniRadijus)
Dodana je i funkcija OnDrawGizmos() u programskom kodu 54 koju Unity vec sa-
drži te je dostupna za vlastitu implementaciju Gizmo se koriste za vizualno traženje
grešaka u programskom kodu ili za postavljanje svojevrsne pomoci u pogledu scene
Ovdje se koriste da se lakše vidi gdje je kursor kliknuo na ekran naprema gdje ce se
igrac zaustaviti kao što se vidi na slici 55 u obliku dvije sfere [2]
Slika 55 Prikaz korištenja gizmo-a
Sve crtanje gizmoa se treba obaviti unutar funkcija OnDrawGizmos ili OnDrawGiz-
mosSelected OnDrawGizmos se poziva u svakom okviru dok se OnDrawGizmosSe-
lected poziva samo ako je objekt na kojem se skripta nalazi selektiran [2]
Funkcija skrati destinaciju je dodana kako bi lik krenuo usporavati ranije prije nego
što se npr zabije u zid te zbog buduce implementacije napadanja na daljinu
34
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
6 Korisnicko sucelje
Korisnicko sucelje je jedno od najbitnijih dijelova svake igre Obicno se koristi za
prikaz osvojenih nagradabodova preostalog života igraca trenutno korištenog oružja
i sl U ovom poglavlju se opisuju neki osnovni koncepti dodavanja korisnickog sucelja
u Unityu Cilj je da se do kraja poglavlja postavi linija s postotkom preostalog života
igraca te linije preostalih života iznad svakog neprijatelja u igri
61 Platno
Platno je objekt s komponentom platno (engl Canvas) na kojeg se slažu svi ostali
elementi korisnickog sucelja koji moraju onda biti djeca tog objekta Kreira ga se s
GameObject -gt UI (korisnicko sucelje (engl User Interface)) -gt Canvas ili bilo cime
iz GameObject -gt UI što automatski onda dodaje platno u scenu ako vec tamo ne
postoji Prikazuje se kao pravokutnik u sceni Svi elementi se crtaju na platno redom
kojim ih se složi u hijerarhiji (lijevi prozor u Unityu) prvo dijete se crta prvo drugo
se crta drugo itd Platno sadrži opciju nacin iscrtavanja (engl Render Mode) s kojom
se odreduje hoce li se platno prikazati u prostoru ekrana ili cijelog svijeta igre Prikaz
u prostoru ekrana se još dijeli i na prikaz u prostoru ekrana - prekrivanje (engl Screen
Space - Overlay) i prikaz u prostoru ekrana - kamera (engl Screen Space - Camera)
Prikaz u prostoru ekrana - prekrivanje iscrtava korisnicko sucelje i njegove elemente
na zaslon na vrhu scene Ako se promijeni velicina scene ili se promijeni rezolucija
platno ce takoder automatski promijeniti svoju velicinu Prikaz u prostoru ekrana -
kamera je slicno samo što ce se platno smjestiti na zadanu udaljenost ispred kamere
Elementi korisnickog sucelja ce biti prikazani tom kamerom što znaci da ce ostale
postavke kamere utjecati na prikaz Npr ako se za kameru odabere perspektivna
distorzija ona ce se odnositi i na te elemente Takoder ako se ekran smanji promjeni
rezoluciju i sl platno ce isto promijeniti svoju velicinu da odgovara kameri Preostaje
još prikaz u prostoru svijeta (engl World Space) Tu ce se platno ponašati kao svi
ostali objekti u sceni Može mu se promijeniti velicina koristeci opciju transformiraj
35
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
pravokutnik (engl Rect Transform) Njegovi elementi ce se prikazati ispred ili iza
ostalih objekata u sceni ovisno o 3D položaju [5]
62 Osnovne komponente
Osnovne komponente koje se dodaju na platno su tekst slike sirove slike (engl Raw
Image) i maska ciji primjer možemo vidjeti na slici 61 Komponenta tekst koja se još
naziva i oznaka (engl Label) ima podrucje za upisivanje teksta koji ce biti prikazan
Moguce je namjestiti font stil fonta velicinu i još ostale opcije za poravnavanje teksta
Slika 61 Osnovne komponente platna
Slika se sastoji od dvije komponente Rect Transform i komponente slike U
komponentu slike se obicno dodaje slika (engl Sprite) u polje ciljni graficki prikaz
(engl Target Graphic) i bira joj se boja u polju boja (engl Color) Takoder se može
dodati i materijal u komponentu slike Polje tip slike (engl Image Type) odreduje kako
ce dodana slika biti prikazana Neke od opcija su jednostavna (engl Simple) - jednako
skalira cijelu sliku rezana (engl Sliced) - koristi 3x3 podjelu slika da promjena veli-
cine ne iskrivi kuteve i samo se središnji dio razvuce poplocana (engl Tiled) - slicna
rezanoj samo se slike ponavljaju umjesto da se rastegnu popunjena (engl Filled) -
prikazuje na isti nacin sliku kao i jednostavni prikaz samo što popuni sliku od ishodi-
šta u zadanom smjeru metodi i kolicini Slike se mogu unijeti kao sprite korisnickog
sucelja tako da se odabere Sprite(2DUI) pod postavkama tip teksture (engl Texture
Type) Razlika izmedu slike i raw image-a je da raw image umjesto sprite slike prima
36
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
teksturu Maska služi kako bi modificirala izgled elemenata svoje djece Ona ogra-
nicava izgled elemenata djece na oblik roditelja Dakle ako je npr dijete vece od
roditelja prikazat ce se samo dio djeteta koje stane unutar oblika roditelja[ ]
63 Korisnicko sucelje igraca
Platno igre ovog projekta se sastoji od tri komponente teksta raw image-a i maske
Tabla koja prikazuje postotak života igraca lako se izradi koristeci program Bojanje
(engl Paint) u kojem napravimo liniju 2048x32 piksela koju podijelimo na dva dijela
Jedan dio se oboja zelenom bojom a drugi crvenom Maska je isto jedna linija velicine
2048x128 piksela koja ce služiti kao okvir Kreira se platno sa Component -gt UI -gt
Canvas Na njega se doda desnim klikom miša UI -gt Tekst (engl Text) cije postavke se
mogu vidjeti na slici 62 Tablu života i masku table života se obje dodaju jednaki pos-
tupkom samo dodamo raw image umjesto teksta UI -gt Raw Image Njihove postavke
se takoder mogu vidjeti na slici 63 Na tablu života se sada dodaje skripta prikazana
programskim kodom 61 koja ce translatirati tu sliku lijevodesno ovisno o preostalom
postotku života igraca
Programski kod 61 tablaZivotaIgracacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
[RequireComponent(typeof(RawImage))]
public class TablaZivotaIgraca MonoBehaviour
RawImage slikaTableZivota
GospodinLijepi gospodinLijepi
void Start()
nadi igraca i sliku table zivota
gospodinLijepi = FindObjectOfTypeltGospodinLijepigt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
37
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
pomici sliku table zivota po x osi za xVrijednost koja
ovisi o postotku zivota igraca
float xVrijednost = -(gospodinLijepipostotakZivota 2f)
- 05f
slikaTableZivotauvRect = new Rect(xVrijednost 0f 05f
1f)
Konacan izgled korisnickog sucelja igraca može se vidjeti na slici 64
Slika 62 Postavke teksta u korisnickom sucelju
64 Korisnicko sucelje neprijatelja
Za ovaj primjer izmodelirani su neprijatelji u obliku vuka Jednakim postupkom kao i
ostali blend modeli povlacenja iz datoteke u kojoj se nalaze se unose u Unity Na njih
se dodaje jednostavna skripta prikazana programskim kodom 62 koja ce odredivati
njihov postotak života
Programski kod 62 neprijateljcs
using SystemCollections
using SystemCollectionsGeneric
38
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 63 Postavke table života i maske table života u korisnickom sucelju
using UnityEngine
public class Neprijatelj MonoBehaviour
[SerializeField] float punZivot = 100f
float trenutnoZivota = 100f
vraca postotak zivota neprijatelja
public float postotakZivota
get
return trenutnoZivota punZivot
Takoder im se mora postaviti layer na Neprijatelj Sad se na neprijatelja desnim
klikom dodaje Create Empty objekt koji ce nam služiti za implementaciju korisnickog
39
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 64 Trenutno korisnicko sucelje igre
sucelja neprijatelja Na taj prazni objekt dodaje se nova skripta prikazana programskim
kodom 63
Programski kod 63 platnoNeprijateljacs
using UnityEngine
public class UINeprijatelja MonoBehaviour
[SerializeField] GameObject platnoNeprijatelja = null
Camera kamera
void Start()
nadi glavnu kameru i postavi platno neprijatelja na
poziciju neprijatelja
kamera = Cameramain
Instantiate(platnoNeprijatelja transformposition
Quaternionidentity transform)
void LateUpdate()
okreci platno neprijatelja ovisno o smjeru pogleda kamere
transformLookAt(kameratransform)
transformrotation = QuaternionLookRotation(kamera
transformforward)
40
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Ta skripta zahtjeva dodavanje platna neprijatelja koje se sastoji samo od table života
Dakle kreira se novo platno i na njega opet raw image table života jednaka kao i kod
platna igraca bez maske i bez teksta To platno se sada može povuci u polje zahti-
jevanog platna neprijatelja skripte Jedina razlika je što ce taj raw image table života
neprijatelja sada na sebi imati prilagodenu skriptu neprijatelju prikazanu programskim
kodom 64
Programski kod 64 tablaZivotaNeprijateljacs
using SystemCollections
using SystemCollectionsGeneric
using UnityEngine
using UnityEngineUI
public class TablaZivotaNeprijatelja MonoBehaviour
RawImage slikaTableZivota = null
Neprijatelj neprijatelj = null
void Start()
pronadi neprijatelja i sliku njegove table zivota
neprijatelj = GetComponentInParentltNeprijateljgt()
slikaTableZivota = GetComponentltRawImagegt()
void Update()
pomici po x osi sliku table zivota ovisno o postotku
zivota neprijatelja
float xValue = -(neprijateljpostotakZivota 2f) - 05f
slikaTableZivotauvRect = new Rect(xValue 0f 05f 1f)
41
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
7 Teren
Sustav za teren koji Unity nudi omogucava dodavanje razlicitih pejzaža u igre Prikaz
terena je jako optimiziran te se teren mijenja i kreira koristeci jednostavne alate Izra-
divanje visinskih mapa i poligona matrica za kretanje programeru obicno predstavlja
poveci problem i uzima dosta vremena Unity to spušta na jako nisku razinu znanja
omogucavajuci korisniku da samo povlacenjem miša mijenja visine brda i dolina svo-
jeg terena Cilj ovog poglavlja je izraditi okvirno teren za igru i nauciti bojati teren
razlicitim teksturama [4]
71 Kreiranje i uredivanje terena
Teren se u scenu dodaje postupkom GameObject -gt 3D Object -gt Teren (engl Ter-
rain) iz menija Dobije se velika ravnina bez ikakvih visinskih anomalija No zato u
prozoru novostvorenog terena postoje mnogi alati za kreiranje raznih detalja kao što se
vidi na slici 71 Vecina alata su zapravo kistovi sa svojim opcijama za velicinu kista
i prozirnost Koristeci te kistove teksture se doslovno bojaju po terenu Skroz lijevi
alat na slici 71 služi za spuštanje ili podizanje terena Ovisno o obliku kista velicini i
jakosti kreiramo razlicite oblike planina dolina i sl Svi alati osim alata za postavljanje
drveca imaju jednake opcije i služe za dodavanje boje biljaka visine i sl [4]
72 Visinske mape
Na slici 72 vidimo tri alata koja služe za mijenjanje visine terena Prvi gumb aktivira
alat za podizanje i spuštanje terena Kada se teren boja s ovim alatom visina ce
se mijenjati kako se prelazi lijevim klikom miša po terenu Visina se povecava ako
se dulje vrijeme drži lijevi klik miša na istom podrucju Ako se drži i shift i lijevi
klik miša visina se spušta Primjer kreiranog terena za projekt može se vidjeti na slici
73 Drugi alat s lijeva na slici 72 je slican osim što se dodatno može odrediti tocno
željena visina Kada se s njime boja po terenu teren ce se spustiti na podrucjima
42
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 71 Alati za kreiranje terena
iznad zadane visine i povisiti na podrucjima ispod nje Takoder ako se želi postaviti
visina na neku koja vec postoji na terenu koja je bila vec korištena ali se ne zna njen
iznos držeci shift klikne se lijevim klikom miša na to podrucje na terenu i postavit
ce se visina alata na tu Uz tu opciju postavljanja visine na zadani iznos postoji i
opcija izravnaj (engl Flatten) koja postavlja cijeli teren na odabranu visinu U ovom
projektu je teren izravnat odmah na visinu 100 kako bi se omogucilo dodavanje dolina
rijeka i sl Ako se teren nalazi na unaprijed zadanoj visini 0 cak i držeci shift ne
može se dodatno spustiti teren jer ne može ici u negativan iznos Treci i zadnji alat
izgladi visinu (engl Smooth Height) ne podiže ni spušta teren znacajno vec izracuna
prosjecnu vrijednost podrucja u blizini To ublažava razliku visina i služi da se teren
neprimjetnije mijenja Visina svake tocke terena je zapravo vrijednost u pravokutnom
nizu Taj niz se može predstaviti koristeci sliku u sivim tonovima koja se zove visinska
mapa (engl Heightmap) Ponekad je bolje raditi na visinskoj mapi u nekom vanjskom
uredivacu kao npr Photoshop-u Unity omogucava uvoz i izvoz visinskih mapa za
teren Na slici 71 se nalazi skroz desni gumb koji predstavlja opcije terena klikom na
njega pojavit ce se dodatna dva gumba uvezi sirovo (engl Import RAW) i izvezi sirovo
(engl Export RAW) Oni omogucuju da se cita iz visinskih mapa ili da se piše u njih
u standardnom RAW formatu koji je 16-bitni format u sivim tonovima kompatibilan s
vecinom uredivaca slika [4]
43
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 72 Alati za mijenjanje visine terena
Slika 73 Primjer kreiranog terena
73 Teksture za teren
Teksture su slike koje se stavljaju na površinu terena da mu se doda detalja boje itd S
obzirom na to da su tereni veliki objekti uobicajeno se dodaju teksture koje se nepri-
mjetno ponavljaju i poplocaju cijelu površinu Ponavljanje ne bi trebalo biti primjetno
igracu Jedna tekstura ce služiti kao bazna tekstura po kojoj se dodaju detaljnije teks-
ture i boje Na slici 71 središnji alat u obliku kista predstavlja alat za bojanje tekstura
U pocetku teren nema nikakvih tekstura za bojanje Nove teksture se dodaju klikom na
uredi teksture (engl Edit Textures) i selektiranjem dodaj teksture (engl Add Texture)
To otvara prozor kao na slici 74 gdje se dodaje tekstura i njene opcije Klikom na se-
lektiraj (engl Select) pojavljuju se teksture koje su od prije ubacene u projekt u odvo-
jenom prozoru Opcija velicine (engl Size) omogucava postavljanje visine i duljine
preko koje ce se tekstura razvuci na površini terena Pomak (engl Offset) odreduje
koliko ce daleko od ishodišta terena poceti poplocavanje teksturom kada je postav-
ljen na 0 poplocavanje pocinje iz desnog kuta Prva tekstura koja se doda se koristi kao
bazna tekstura i prekrit ce cijeli prethodno napravljeni teren Sve ostale teksture koje se
naknadno dodaju mogu se stavljati po terenu koristeci alate kista Opet se postavljaju
opcije vidljivosti i velicine kista te se lijevim klikom miša samo bojaju po terenu [4]
44
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Slika 74 Dodavanje novih tekstura za teren
45
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
8 Zakljucak
Unity je razvojna okolina koja pruža beskonacno mnogo razlicitih mogucnosti Kroz
ovaj rad su se obradile neke osnovne tehnike koje pomažu citatelju da postavi sve
osnovne stvari potrebne za kreiranje scena i nivoa u svojoj igri Znanje objektno ori-
jentiranog programiranja i racunarske grafike sigurno pruža prednost pri proucavanju
materijala Krenulo se od prazne scene i bez ikakvog predznanja rada s Unityem Za
svaki problem na koji se naišlo postojao je veliki broj razlicitih rješenja ali su unutar
ovog rada bolje ili lošije riješeni na ovaj nacin Svaka igra je posebna i sastoji se od
vlastitih mehanika i problema tako da ne postoji jedan algoritam po kojem se može
kreirati potpuno funkcionalna igra Potrebna je velika kolicina vremena i široko po-
drucje znanja da se samostalno isprogramira i dizajnira sve željene komponente Unity
je definitivno odlican alat za pocetnike koji pomaže pri snalaženju i ucenju najcešce
korištenih rješenja u svijetu kreiranja igara
46
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
9 Zasluge
Kursore napravio Freepik od Flaticon licencirano Creative Commons BY 30
47
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
LITERATURA
[1] Unity User Manual (20171 beta) Cameras URL httpsdocsunity3d
com20171DocumentationManualCamerasOverviewhtml
[2] Unity User Manual (20171 beta) Gizmos URL httpsdocsunity3d
comScriptReferenceGizmoshtml
[3] Unity User Manual (20171 beta) Navigation and Pathfinding URL
httpsdocsunity3dcom20171DocumentationManual
Navigationhtml
[4] Unity User Manual (20171 beta) Terrain Editor URL https
docsunity3dcom20171DocumentationManual
script-Terrainhtml
[5] Unity User Manual (20171 beta) UI URL httpsdocsunity3dcom
20171DocumentationManualUISystemhtml
[6] Cupic i Mihajlovic Interaktivna racunalna grafika kroz primjere u OpenGL-u
2016
48
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
Izrada digitalnih 3D igara u razvojnoj okolini Unity
Sažetak
Postavlja se pocetna scena i unosi blend model glavnog lika Rješavaju se problemi
vezani uz animacije hodanje gravitaciju svijeta i kontrole Objašnjavanje razlicitih vr-
sta kamera i bacanja zraka te biranje prave kamere za igru u projektu Implementacija
navigacijskog sustava i kodiranje kontrola kretanja Kreiranje korisnickog sucelja za
igraca i neprijatelje Izrada terena i dodavanje tekstura terenu
Kljucne rijeci Unity blend model kamera navigacijski sustav teren korisnicko
sucelje animacije kretanje bacanje zraka
Creating 3D games in Unity game engine
Abstract
Creating a scene and importing blend model of the main game character Dealing
with animation moving gravitation of the world and control problems Explaining
different camera versions and ray casting choosing the right camera for the game in
the project Implementing NavMesh system and coding moving controls Creating a
user interface for the player and the enemies Creating terrain and adding textures to
it
Keywords Unity blend model camera NavMesh terrain user interface animations
moving ray casting
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
POPIS MODELA
Svi modeli napravljeni u Blenderu skupa sa svojim teksturama i materijalima su uklju-
ceni u ovaj završni rad Njihov popis nalazi se ispod
bull lik viteza (GospodinLijepi)
bull drvo
bull drvo1
bull drvo2
bull mac
bull vuk
bull srednjovjekovna kuca
bull most
bull drvena kabina
50
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51
POPIS PROGRAMSKIH KODOVA
21 HelloWorld1cs 5
22 HelloWorld2cs 5
41 PrimjerViseKameracs 13
42 pratiLikacs 15
43 lociranjeKursoracs 17
44 povecavanjeSlikecs 18
51 bacanjeZrakacs 22
52 kretanjecs 27
53 kursorcs 28
54 kretanjecs 30
61 tablaZivotaIgracacs 37
62 neprijateljcs 38
63 platnoNeprijateljacs 40
64 tablaZivotaNeprijateljacs 41
51