Professional Documents
Culture Documents
PRIRODNO-MATEMATIČKI FAKULTET
DEPARTMAN ZA RAČUNARSKE NAUKE
Master rad
Mentor: Student:
Prof. dr Marko D. Petković Filip Stojanović
br. Indeksa 79
Niš, 2017
Virtuelna realnost: Osnove i izrada igara
Sadrţaj
1. Uvod.………………………………………………………………………..2
1.1. Šta je Virtuelna realnost?...........................................................................2
1.2. Istorija i razvoj Virtuelne realnosti………………………………………3
1.3. Tipovi naočara (Head-Mounted Display)………………………………..3
1.4. Razlika izmeĎu VR, AR i MR…………………………………………...4
1.5. Igre i aplikacije…………………………………………………………..5
2. Unity, Oculus I Virtuelna realnost………………………………….....6
2.1. Šta je Unity?..................................................……………………………6
2.2. Šta je Oculus?..………………………………………………………….6
2.3. Mobile VR principi………………………………………………………7
2.4. Optimizacija…………………………………………………………….8
2.5. Kretanje…………………………………………………………………9
2.6. Interakcija igrača………………………………………………………..9
2.7. Korisnički interfejs……………………………………………………...9
3. Novi projekat…………………………………………………………..…11
3.1. Kreiranje projekta………………………………………………………11
3.2. Editor i layout…………………………………………………………..12
3.3. Podešavanja projekta………………………………………………...…13
4. Projekat "VR Master"…………………………………………………...14
5. Prirodno-matematički fakultet – prezentacija u 360 stepeni………….……16
5.1. Postavljanje slika……………………………………………………….17
5.2. Kretanje korisnika……………………………………………………...17
5.3. Podaci o kabinetima i profesorima……………………………………..19
5.4. Firebase skladište……………………………………………………….19
5.5. Parsiranje XML-a………………………………………………………22
5.6. Dinamičko kreiranje liste………………………………………………23
6. VR Survival Shooter igra……………………………………………….26
6.1. Igrač………………………………………………………………….…26
6.2. Pojačanja igrača (power up)……………………………………………30
6.3. Neprijatelji…………………………………………………………...…33
7. Oculus prodavnica I developer konzola……………………………...38
8. Zaključak……………………...…………………………………………..39
9. Literatura……………………………...…………………………………..40
1
Virtuelna realnost: Osnove i izrada igara
1. Uvod
2
Virtuelna realnost: Osnove i izrada igara
3
Virtuelna realnost: Osnove i izrada igara
Desktop VR. Ovde spadaju HMD ureĎaji koji su povezani kablovima na računare ili
konzole koje imaju jače grafike. Igra se pokreće na mašini a prikazuje se na HMD-u.
Ovde spadaju Oculus Rift, HTC Vive i Playstation VR.
Mobile VR. Najjednostavniji primer mobile VR-a je Google Cardboard, jednostavno
kućište (obično od kartona) sa dva sočiva i mestom za mobilni telefon. Telefon
prikazuje dva stereografska prikaza i ima senzor za rotaciju glave, ali ne i za poziciju.
TakoĎe postoji i dugme za klik kojim korisnik interaguje sa aplikacijom. Kvalitet i
performanse su ograničene, jer aplikaciju pokreće procesor telefona. Pored Google
Cardboard-a ovde spadaju i Samsung Gear VR i Google Daydream.
Sve tri oblasti obećavaju dosta toga u budućnosti, ali različitog. Dok AR angaţuje
korisnika da interaguje sa trenutnom okolinom, virtuelna realnost u potpunosti uranja u novu
okolinu i iskustvo. U AR moţete na svom stolu stvoriti plan neke kuće, okretati ga i studirati,
dok u VR moţete ući u tu kuću i kretati se njom. HoloLens će omogućiti povezivanje ove dve
stvari tako što će korisnik trenutno okruţenje moći da pretvori u nešto sasvim novo po ţelji.
4
Virtuelna realnost: Osnove i izrada igara
5
Virtuelna realnost: Osnove i izrada igara
6
Virtuelna realnost: Osnove i izrada igara
Oculus trenutno ima dve onlajn prodavnice za skidanje igara i aplikacija. Posebna
prodavnica je za Rift a posebna za Gear VR jer je hardver telefona dosta slabiji od računara
pa samim tim su i igre za Samsungov Gear VR dosta slabije. Prodavnica za Gear VR iz
samog ureĎaja je prikazana na slici 2.2.
Iako su principi programiranja za svaki head-mounted display slični, za svaki od njih
potreban je poseban development kit koji se uključuje u Unity. Oculus ima poseban SDK za
Rift i Gear VR. Počev od Unity verzije 5.1, Oculus SDK je uključen u ovaj game engine pa
developeri mogu praviti igre za Oculus prodavnice bez dodatnog skidanja SDK.
7
Virtuelna realnost: Osnove i izrada igara
Za svaki od ovih koraka Oculus nudi smernice koje developeri trebaju pratiti kako bi
njihov proizvod bio zadovoljavajuć i kako bi prošao test i proveru. Smernice su podeljene u
pet kategorija i to su kompatibilnost, funkcionalnost, grafika i performanse, bezbednost i
interakcija korisnika.
Kompatibilnost osigurava da aplikacija ostane kompatibilna sa Oculus-ovim
bibliotekama i da developer vodi računa o hardverskim specifikacijama koje Oculus
preporučuje. UreĎaji koji trebaju biti podrţani su svi Samsung S modeli od S6 do
najnovijeg S8 i Note 4 i 5 modeli. C i C++ aplikacije moraju biti pisane da podrţavaju
Oculus SDK 1.60 i noviji. Tu su i preporučene verzije Unity game egine na kojima
kojima Oculus SDK radi. Developer mora koristiti jednu od tih verzija kako bi Oculus
SDK funkcionisao.
Funkcionalnost obezbeĎuje da aplikacija funkcioniše po Oculus-ovim standardima.
Igre za jednog igrača se moraju pauzirati kada igrač skine HMD ili se vrati u
univerzalni meni takoĎe aplikacija ne sme iscrtavati frejmove niti prihvatati unos.
Igrač nikada ne sme biti "zaglavljen" u aplikaciji, npr. kod ekrana za login mora
postojati opcija za kreiranje naloga. Ukoliko aplikacija zahteva internet a njega nema,
korisnik se mora obavestiti o njegovoj potrebi. Aplikacija ne sme izgubiti snimljene
podatke korisnika.
Grafika i performanse su veoma bitni u VR igrama. Ako je grafika loša ili igra
sporo radi, korisniku moţe biti neprijatno i moţe osetiti mučninu. Aplikacija mora
raditi na 60fps konstantno inače će se korisnik osećati nelagodno. Više o "ceĎenju
performansi" za Unity VR igre za telefone moţe se naći na adresi -
https://developer.oculus.com/blog/squeezing-performance-out-of-your-unity-gear-vr-
game/. Aplikacija mora raditi bez zamrzavanja i pucanja. Pri pokretanju aplikacije
scena se mora pojaviti u roku od 4 sekunde, u suprotnom treba da se obezbedi loading
ekran. CPU i GPU (Central & Graphics processing unit - procesor i grafčki čip) se
moraju koristiti najefikasnije kako se telefon ne bi pregrevao i brzo potrošio bateriju.
Bezbednost traţi da se zaštite privatnost i integritet Oculus-ovih i korisnikovih
podataka. Aplikacija mora zahtevati minimalan broj permisija za funkcionisanje.
Ukoliko se neki podaci šalju eksternom servisu korisniku se to mora naglasiti.
Interakcija korisnikamora biti po Oculus-ovim standardima. Back i home dugme
moraju funkcionisati uvek isto kao što Oculus nalaţe. Ukoliko aplikacija zahteva
kontroler, korisniku se to mora napomenuti. Ako je kontroler podrţan, korisnik mora
da ima opciju da bira izmeĎu kontrolera i touch pad-a. TakoĎe aplikacija mora
detektovati da li se kontroler nalazi sa leve ili desne strane.
2.4. Optimizacija
Kod VR igara optimizacija je veoma vaţna, pogotovu ako je to igra za Gear VR.
Postoje razni trikovi koji mogu pomoći u optimizaciji igara. Jedan od njih je static batching.
Svi objekti na sceni koji se ne pomeraju mogu biti označeni kao statični i tada će ih Unity
iscrtavati kao jedan objekat. Još je bolje da ti objekti koriste jedan materijal jer za svaki
materijal na sceni Unity pravi jedan draw call (poziv za crtanje). Maksimalni broj draw call-
ova na sceni treba biti 50. Ovde se moţe koristiti texture atlasing, jedna velika tekstura koja
u sebi sadrţi teksture svih statičnih objekata i ona se postaviti kao materijal za sve objekte.
Nakon toga se objekti mapiraju i označava se koji deo teksture da koriste.
Dobar level dizajn moţe dosta optimizovati igru. Npr. ukoliko se igrač kreće iz sobe
u sobu, loša praksa je učitati sve sobe na početku, već ih treba učitavati pri ulasku igrača u
8
Virtuelna realnost: Osnove i izrada igara
nju. Loša strana toga je što bi se onda koristilo više memorije pri učitavanju svakog objekta.
Zato je najbolje sobe odvojiti po nivoima i asinhrono ih učitavati po potrebi iz koda.
Asoinhrono učitavanje nivoa je veoma korisno ukoliko igra ima velike nivoe. Pre
nego što igrač napusti jednu sobu, sledeća se moţe učitati asinhrono sa
Application.LoadLevelAsync().
Ukoliko se nivo učita klasično bez asinhronog učitavanja, igra će se zamrznuti dok se sledeći
nivo ne učita.
Bejkovanje svetla je veoma vaţno ne samo u VR igrama. Svim statičnim objektima
mogu se isključiti realtime senke i nakon toga bejkovati osvetljenje. Na taj način pravi se
tekstura sa senkama koja se iscrtava statično umesto "ţivih" senki koje se iscrtavaju u
svakom frejmu.
2.5. Kretanje
Kretanje je veoma vaţan faktor koji uslovljava zadovoljstvo igrača. Ukoliko u igri
postoji neki način kretanja on mora biti što pribliţniji prirodnom. U suprotnom kod igrača se
javlja mučnina koja se drugačije zove VR bolest. Javlja se zbog toga što je telo igrača u
pravom svetu statično dok se u virtualnom svetu kreće. Najbolje je izbegavati kretanje osim
ako ono ne kopira pravo kretanje igrača jer moţe uticati na vestibularni sistem (sistem organa
za ravnoteţu).
Kod klasičnih igara u prvom licu često se javlja mučnina, zato je najbolje izbegavati
ih. Ako developer ipak odluči za ovaj tip igre najbolje je testirati kretanje sa što više
korisnika. Jedno rešenje za FPS igru je pravljenje konstantne statične vizuelne reference kao
što je kokpit, kabina ili unutrašnjost auta.
Popularna metoda kretanja je Fade/Blink tranzicija. Igrač se kreće sa jedne pozicije
na drugu tako što se kamera brzo zamrači da korisniku ispred očiju bude samo crna boja,
nakon toga se kamera pomeri na novu poziciju i crna boja se skloni. Ovo je jedan od
najprijatnijih i najjednostavnijih načina kretanja igrača.
9
Virtuelna realnost: Osnove i izrada igara
Kod običnih igara koje nisu VR, interfejs se nalazi preko svega na ekranu i zove se
HUD (Heads Up Display). To je non-diegetic interfejs, interfejs koji se ne nalazi u sklopu
sveta, ali ima smisla za igrača kao posmatrača igre. To su obično energija igrača, rezultat itd.
Pojam diegetic je preuzet iz filmske industrije gde je non-diegetic zvuk pozadinska muzika u
nekom filmu ili TV emisiji, a diegetic zvuk bi bio neki razgovor npr. Primer non-diegetic
interfejsa moţemo videti u igri World of Warcraft gde su magije, razgovori, energija i mapa
na samoj kameri (slika 2.4).
Slika 2.4: World of Warcraft non-diegetic interface Slika 2.5: Forza 4 spatial interface
Spatial ili prostorni korisnički interfejs bi bio interfejs koji se nalazi u samom svetu
igre. To moţe biti glavni ili neki pomoćni meni u igri kao u igri Forza 4 (slika 2.5). Kod ovog
interfejsa veoma je bitno obratiti paţnju na udaljenost od korisnika. Ukoliko je isuviše blizu,
korisnik će naprezati oči, a ako je isuviše daleko činiće se kao da je fokus na horizontu.
Najbolje je pozicionirati interfejs na razdaljini od par metara od korisnika, i skalirati slike i
tekst da budu vidljive i prijatne za čitanje.
Developeri obično u početku korisnički interfejs lepe za kameru tako da se ostane na
fiksnoj poziciji dok se igrač kreće. To moţe biti korisno za neke manje stvari u interfejsu, dok
će velike stvari stvoriti utisak kao da sve vreme drţite novine ispred lica pokušavajući da
gledate naokolo što moţe dovesti do nelagodnosti.
10
Virtuelna realnost: Osnove i izrada igara
3. Novi projekat
11
Virtuelna realnost: Osnove i izrada igara
VR igre u 3D svetu, a assete učitati naknadno iz Unity editora. Klikom na "Create project"
Unity kreira sve potrebne fajlove za projekat i otvara Unity editor (slika 3.2).
12
Virtuelna realnost: Osnove i izrada igara
Sledeća stvar koju trebamo uraditi je promena platforme. Pri kreiranju novog projekta
podrazumevana platforma je PC, Mac i Linux. U meniju File > Build Settings moţemo
izabrati Android i kliknuti na Switch Platform. Nakon toga moţemo preći na podešavanja za
Android odabirom Player Settings opcije (slika 3.5).
U inspektoru se otvara PlayerSettings gde imamo opšta podešavanja za projekat
(slika 3.6.). Prvo unosimo ime kompanije koja je vlasnik projekta ili naloga na koji će igra
biti postavljena. Nakon toga unosimo ime koje će se prikazivati na ureĎaju kada se igra
instalira. Ukoliko ne izaberemo neku ikonicu za projekat, Unity će dodeliti svoj logo kao
13
Virtuelna realnost: Osnove i izrada igara
podrazumevanu. Splash Image, slika koja se prikazuje pri učitavanju igre, moţe da se
promeni samo ako imamo plaćenu verziju Unity-a. U suprotom moţemo samo dodati još
neku splash sliku. U Other Settings imamo podešavanja za Color Space koja odreĎuje kako
će se boje mešati sa osvetljenjem i tu biramo Linear. Za Graphics API isključujemo Auto
opciju i u listi ostavljamo samo OpenGLES3 i Vulkan jer je OpenGLES2 grafika isuviše
slaba za VR. OpenGLES je interfejs za renderovanje (iscrtavanje) grafike u aplikacijama.
Obavezno štikliramo Virtual Reality Supported i iz padajuće liste izaberemo Oculus. Kod
identifikacije biramo Package Name koji nam identifikuje igru na storu jer svaka aplikacija
ima svoj package name koji se mora razlikovati od svih ostalih. TakoĎe unosimo i trenutnu
verziju projekta. Minimum API za VR igre je Android 5.0. Na kraju u Publish Settings
unosimo ključ sa koji obezbeĎuje aplikaciju. Taj isti ključ kasnije koristimo za ponovno
pakovanje aplikacije.
Nakon svih podešavanja moţemo početi izradu igre za virtuelnu realnost. Projekat
koji se koristi kao primer u ovom radu podrţava Samsung Gear VR ureĎaj. U njemu ćemo
videti neke od principa VR-a koje smo prethodno pomenuli i kako se oni koriste.
Projekat se sastoji iz dva dela. Prvi deo je prezentacija Prirodno-matematičkog
fakulteta u 360 stepeni. Korisnik se nalazi u sferama na kojima se nalaze slike u 360 stepeni
koje su napravljene Samsung Gear 360 kamerom i kreće se iz jednog dela fakulteta u naredni
teleportovanjem.
Drugi deo projekta je VR Survival Shooter igra u kojoj se igrač nalazi u jednom kraju
sobe dok iz drugog kraja ka igraču kreću raznolika čudovišta. Kada čudovišta stignu do
igrača napadaju ga i polako ubijaju. Cilj igre je da igrač što duţe preţivi napad i sakupi što
veći broj poena uništavanjem čudovišta.
U projektu ćemo imati četiri scene (slika 4.1) Preload, Enter, Sphere i Game
Scene. Na preload sceni neće biti ničega osim osim jednog objekta koji će nam sluţiti za
učitavanje Firebase-a što ćemo videti kasnije u radu. Scene u Unity-u funkcionišu kao
odvojeni nivoi i svaka se dizajnira zasebno.
14
Virtuelna realnost: Osnove i izrada igara
Pri pokretanju scene odmah se učitava naredna scena jer ona sluţi samo za učitavanje
podešavanja za projekat. Kameru ćemo podesiti tako što podešavamo Clear Flags na Solid
Color i biramo crnu boju. U slučaju da se naredna scena ne učita odmah, neće se videti
prazan prostor nego će korisnik videti crnu boju. Novu scenu učitavamo sa:
SceneManager.LoadScene("EnterScene");
Naredna scena je Enter Scene na kojoj se nalaze vrata za prethodno pomenute delove
projekta, prezentaciju u 360 stepeni i survival shooter igru (slika 4.2). Sama rotacija kamere
je automatski ubačena uključivanjem podrške za Gear VR. Jedna od stvari koja nam je
potrebna u ovom trenutku je interakcija igrača. Ceo prefab sa Main kamerom i Reticle-om
koji se koristi za interackiju moţemo naći u VR Samples assetu na adresi
https://www.assetstore.unity3d.com/en/#!/content/51519. Prefab je objekat sa unapred
odreĎenim svojstvima koji je spreman za ubacivanje na scenu.
Ubacivanjem ovog prefab-a na centru ekrana dobijamo Reticle, belu tačku koja
funkcioniše kao meta (slika 4.3). Klikom na touch-pad registruje se klik na onaj objekat na
kome se nalazi Reticle. Interakcija se vrši tako što se iz pravca kamere pravo pušta zrak koji
pogaĎa ciljani objekat. Funkcija za to se nalazi u skripti VREyeRaycaster.cs:
private void EyeRaycast()
{
// Kreiranje zraka koji ide pravo od kamere.
Ray ray = new Ray(m_Camera.position, m_Camera.forward);
RaycastHit hit;
// Pustanje zraka unapred i detektovanje mete
if (Physics.Raycast(ray, out hit, m_RayLength, ~m_ExclusionLayers))
{
//pokušavamo da dobijemo VRInteractiveItem skriptu pogođenog objekta
VRInteractiveItem interactible = hit.collider.GetComponent<VRInteractiveIte
m>();
15
Virtuelna realnost: Osnove i izrada igara
m_CurrentInteractible = interactible;
// Nešto smo pogodili i postavljamo Reticle na tu poziciju.
if (m_Reticle)
m_Reticle.SetPosition(hit);
if (OnRaycasthit != null)
OnRaycasthit(hit);
}
else
{
// Ništa nismo pogodili i postavljamo Reticle na podrazumevanu razdaljinu.
if (m_Reticle)
m_Reticle.SetPosition();
}
}
16
Virtuelna realnost: Osnove i izrada igara
17
Virtuelna realnost: Osnove i izrada igara
GameObject cameraHolder;
private VRInteractiveItem m_InteractiveItem;
private void Awake (){
m_InteractiveItem = gameObject.GetComponent<VRInteractiveItem> ();
cameraHolder = GameObject.Find ("MainCameraHolder");
cameraFade = GameObject.Find ("MainCamera").GetComponent<VRCameraFade> ();
startScale = gameObject.transform.localScale;
biggerScale = new Vector3 (startScale.x + 0.005f,
startScale.y + 0.005f, startScale.z + 0.005f);
}
18
Virtuelna realnost: Osnove i izrada igara
funkcija pomera cameraHolder u centar nove sfere, sklanja fade prelaskom iz crne boje u
transparentnu i gasi prethodnu sferu.
Firebase je Google-ov onlajn servis i sadrţi mnoštvo opcija kao što su baza podataka,
izveštaji o greškama, sinhronizacija ureĎaja, autentikacija korisnika, skladištenje podataka na
oblaku (cloud), hosting i praćenje performansi. Servis je besplatan i moţe se ugraĎivati u
Android, iOS i Unity projekte, a moţe se koristiti već postojeći Google nalog za pristup
konzoli. Mnoge poznate aplikacije, kao što su Shazam, Duolingo, Trivago i druge, koriste
Firebase servise.
U ovom projektu koristićemo Firebase Cloud Storage za onlajn skladištenje XML
fajla kome će naša aplikacija pristupati kako bi prikupila podatke o kabinetima i profesorima
na fakultetu.
19
Virtuelna realnost: Osnove i izrada igara
Klikom na Create Project nakon par sekundi se kreira projekat i otvara Firebase
konzola (slika 5.5). Sa leve strane konzole moţemo videti spisak svih proizvoda koje nudi
ovaj servis. Nama je potreban Storage gde se nalazi forma za upload novog fajla i spisak
postojećih fajlova koji se već nalaze u skladištu. Novi fajl dodajemo tako što kliknemo
dugme Upload File i izaberemo ţeljeni fajl sa našeg računara.
Da bi svi korisnici mogli da pristupe našem fajlu, moramo podesiti njegovu privatnost
u pravilima skladišta. Odabirom opcije Rules na vrhu konzole otvara se polje za editovanje
teksta gde su upisana pravila. Da bi fajl bio javni i dostupan svima trebamo upisati sledeće:
20
Virtuelna realnost: Osnove i izrada igara
service firebase.storage {
match /b/vr-master-rad.appspot.com/o {
match /{allPaths=**} {
allowread, write;
}
}
}
void Awake () {
DontDestroyOnLoad(gameObject);
StartCoroutine(DownloadFromFirebaseStorage());
SceneManager.LoadScene("EnterScene");
}
IEnumerator DownloadFromFirebaseStorage()
{
StorageReference reference = FirebaseStorage.DefaultInstance
.GetReferenceFromUrl("gs://vr-master-rad.appspot.com/kancelarije.xml");
var task = reference.GetBytesAsync(1024 * 1024);
yield return new WaitUntil(() => task.IsCompleted);
if(task.IsFaulted)
{
Debug.Log(task.Exception.ToString());
} else
{
fileContents = Encoding.UTF8.GetString(task.Result);
xmlLoaded = XMLParser.loadXML(fileContents);
}
}
}
21
Virtuelna realnost: Osnove i izrada igara
22
Virtuelna realnost: Osnove i izrada igara
Kada se završi download fajla i ispravan rezultat smesti u string, poziva se funkcija
loadXML(string content) koja se nalazi u skripti XMLParser.cs.
public class XMLParser : MonoBehaviour {
foreach(XmlElement kc in xmlDoc.SelectNodes("fakultet/kancelarija"))
{
Kancelarija kancelarija = new Kancelarija();
kancelarija.brojKancelarije = kc.GetAttribute("br");
kancelarija.imeKancelarije = kc.GetAttribute("ime");
kancelarija.imena = new ArrayList();
foreach(XmlElement ime in kc.SelectNodes("tekst"))
{
string i = ime.InnerText;
Debug.Log(">>" + i);
kancelarija.imena.Add(i);
}
fakultet.kancelarije.Add(kancelarija);
}
return true;
}
}
Za parsiranje XML-a koristimo dve pomoćne klase Fakultet koja sadrţi javnu listu
kancelarija, i klasu Kancelarija koja kao promenljive ima javne stringove
brojKancelarije i imeKancelarije i javnu listu imena.
String koji smo prosledili funkciji kao parametar učitavamo u novu promenljivu tipa
XmlDocument i kreiramo jednu promenljivu tipa Fakultet u koju ćemo smestiti sve
kancelarije.
Uz pomoć foreach petlje prolazimo kroz sve čvorove dokumenta koji su tipa
“kancelarija”. Za svaki od njih kreiramo novu promenljivu tipa Kancelarija, u nju
smeštamo atribute dobijene funkcijom GetAttribute i pravimo novu listu u koju smeštamo
osobe.
Novom foreach petljom prolazimo kroz sve čvorove sa imenom “tekst” i njihovu,
vrednost koju dobijamo funkcijom InnerText, dodajemo u prethodno kreiranu listu.
Nakon završetka parsiranja XML-a, ukoliko je sve proteklo bez greške, potvrĎujemo
da je parsiranje uspešno završeno kako bi kasnije u prezentaciji mogla da se generiše
dinamička lista kabineta i profesora.
23
Virtuelna realnost: Osnove i izrada igara
u kojoj su ispisani kabineti za taj deo fakulteta i osobe koje se nalaze u tim kabinetima a
sličica sa slovom “i” se menja u sličicu za gašenje sa znakom “X”.
Objekat koji sadrţi listu u koju se dinamički dodaju elementi naziva se InfoBG i
nalazi se u Canvas-u (slika 5.6), osnovnom elementu za korisnički interfejs još od Unity
verzije 4.6. Komponenta koju sadrţi ovaj objekat i koja je zaduţena za pravljenje liste je
Vertical Layout Group (slika 5.7)
Objekti koji se dodaju kao deca objekta InfoBG se automatski reĎaju jedan ispod
drugog. Da bi imalo dovoljno mesta za upis imena, štiklirana je opcija Child Force
Expand Width koja raširi svu decu na maksimalnu širinu.
Postoje dva tipa objekata koje ćemo instancirati u listu, to su prefabovi
Kancelarija i Osoba. Oba su objekti koji sadrţe komponentu Text s tim što su boja i
veličina slova predefinisani tako da se razlikuju i budu lako čitljivi u listi i komponentu
Layout Element kako bi ih lista registrovala kao elemente liste.
Na objektu InfoButton se nalazi skripta VRInteractiveItem.cs kako bi on bio
interaktibilan i InfoScript.cs koja je zaduţena za generisanje liste.
public class InfoScript : MonoBehaviour {
[SerializeField]
public string[] brojKancelarije; //brojevi kancelarija
public Sprite infSprite; //slika za info dugme
public Sprite closeSprite; //slika za zatvaranje liste
public Canvas infoCanvas; //Canvas u kome se nalazi lista
public VerticalLayoutGroup VerticalList; //Lista u koju se instanciraju objekti
public GameObject KancelarijaPrefab; //prefab za kancelariju
public GameObject ProfesorPrefab; //prefab za imena profesora
bool infoOpened; //flag koji oznacava da li je lista otvorena ili ne
SpriteRenderer sprite;
VRInteractiveItem interactiveItem;
void Awake () {
interactiveItem = GetComponent<VRInteractiveItem>();
sprite = GetComponent<SpriteRenderer>();
infoOpened = false;
if (FirebaseAgent.xmlLoaded)
{
foreach(Kancelarija k in XMLParser.fakultet.kancelarije)
{
foreach(string s in brojKancelarije)
{
if (k.brojKancelarije.Equals(s))
{
GameObject kancelarija =
24
Virtuelna realnost: Osnove i izrada igara
Instantiate(KancelarijaPrefab) as GameObject;
kancelarija.transform.SetParent(VerticalList.transform, false);
kancelarija.GetComponent<Text>().text =
k.brojKancelarije + " " + k.imeKancelarije;
foreach(string ime in k.imena)
{
GameObject profesor =
Instantiate(ProfesorPrefab) as GameObject;
profesor.transform.SetParent(VerticalList.transform, false);
profesor.GetComponent<Text>().text = ime;
}
}
}
}
}
infoCanvas.gameObject.SetActive(false);
if (!FirebaseAgent.xmlLoaded) {
gameObject.transform.parent.gameObject.SetActive (false);
}
}
private void OnEnable(){
interactiveItem.OnDown += ToggleOpenClose;
}
private void OnDisable() {
interactiveItem.OnDown -= ToggleOpenClose;
}
Parametre u ovoj skripti unosimo iz Unity Editora direktno i tako podešavamo koji
info će prikazivati koje kabinete (slika 5.8).
25
Virtuelna realnost: Osnove i izrada igara
Prvo unosimo koliko će kancelarija biti prikazano u listi, a nakon toga brojeve tih
kancelarija kao elemente niza. Ostali parametri su uvek isti na svim info objektima. U Awake
funkciji prvo proveravamo da li je uspešno izvršeno parsiranje XML-a, ukoliko jeste
popunjavamo listu tako što uporeĎujemo brojeve kancelarija iz XML-a i brojeve koji su uneti
u listu brojKancelarije. Ako se brojevi poklapaju instanciramo objekat Kancelarija,
stavljamo ga kao dete u listu, podešavamo tekst i foreach petljom prolazimo kroz imena
svih osoba koje se nalaze u toj kancelariji. Za svako ime instanciramo objekat Osoba i
podešavamo mu tekst. Ukoliko učitavanje XML-a nije uspešno, gasimo ceo holder za listu.
Funkcija ToggleOpenClose() omogućava paljenje i gašenje liste klikom na dugme
"i" ili "X". Ako je lista zatvorena, menja se sličica u "X" i pali se lista. U suprotnom postavlja
se sličica "i" i gasi lista.
Drugi deo projekta je igra "VR Survival Shooter", first person shooter čiji je cilj što
duţe preţivljavanje napada čudovišta. Igri se pristupa iz Enter scene klikom na vrata sa leve
strane.
Igrač se nalazi u jednom kraju prostorije sa visokim zidovima. Na drugom kraju
prostorije stvaraju se čudovišta koja imaju jedan cilj, a to je uništenje igrača. U ruci igrač ima
pištolj kojim puca na čudovišta i na taj način im skida energiju i ubija ih. Svakim uništenjem
čudovišta igrač dobija odreĎeni broj poena. Na Enter sceni iznad vrata stoji najveći rezultat
koji je igrač postigao. Kraj igre je uvek isti i to je uništenje igrača koje je neizbeţno.
Elementi igre su sam igrač, čudovišta, pojačanja za igrača (power up), način
instanciranja čudovišta i vrste čudovišta. Svaki od ovih elemenata ima svoju logiku kroz koju
ćemo proći u ovom radu.
6.1. Igrač
U ovoj FPS igri kod igrača se vidi samo ruka i pištolj. Igrač ima odreĎenu količinu
energije koja se smanjuje kada neko od čudovišta priĎe dovoljno blizu. Kretanje je
26
Virtuelna realnost: Osnove i izrada igara
onemogućeno jer bi zbog dosta okretanja igraču bilo neprijatno i osetio bi mučninu. Na
svojoj statičnoj poziciji igrač moţe da se okreće i na taj način nišani čudovišta. Reticle koji se
nalazi na sredini ekrana sluţi kao nišan.
Korisnik puca na čudovišta pritiskom touch pad-a na Gear VR ureĎaju. Pucanje se
vrši uz pomoć PlayerShooting.cs skripte koja izgleda ovako:
public class PlayerShooting : MonoBehaviour
{
public int damagePerShot = 20;
public float timeBetweenBullets = 0.20f;
public float range = 100f;
float timer;
Ray shootRay = new Ray ();
RaycastHit shootHit;
int shootableMask;
ParticleSystem gunParticles;
LineRenderer gunLine;
AudioSource gunAudio;
float effectsDisplayTime = 0.2f;
public PowerUpScript powerUpScript;
[SerializeField]
VRInput vrInput;
void Shoot ()
timer = 0f;
gunAudio.Play ();
gunParticles.Stop ();
gunParticles.Play ();
gunLine.enabled = true;
gunLine.SetPosition (0, transform.position);
shootRay.origin = transform.position;
shootRay.direction = transform.forward;
if (Physics.Raycast (shootRay, out shootHit, range, shootableMask)) {
EnemyScript enemyHealth = shootHit.collider.GetComponent <EnemyScript> ();
PowerUpScript powerUp = shootHit.collider.GetComponent<PowerUpScript>();
if (enemyHealth != null) {
enemyHealth.TakeDamage (
Mathf.FloorToInt(PowerUpManager.atackOn * damagePerShot),
27
Virtuelna realnost: Osnove i izrada igara
shootHit.point);
} else if (powerUp != null) {
powerUp.PickUpPowerUp();
}
gunLine.SetPosition (1, shootHit.point);
}
else {
gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
}
}
}
Na početku se nalaze parametri koji odreĎuju koliko će brzo igrač pucati, tj vreme
izmeĎu ispaljivanja metkova timeBetweenBullets i damagePerShot koji odreĎuje štetu
koju igrač nanosi čudovištima. Promenljiva timer nam sluţi za merenje vremena izmeĎu
ispaljivanja metkova.
U funkciji HandleDown() koja se poziva pri kliku na touch pad, u slučaju da je
prošlo potrebno vreme za ispaljivanje meta, pozivamo funkciju Shoot() koja reguliše
ispaljivanje metka.
Osim puštanja zvučnih i vizuelnih efekata pri svakom ispaljivanju metka, u ovoj
funkciji se pusta zrak iz kamere u pravcu nišana. U slučanu da zrak pogodi nešto, ispituje se
da li je taj objekat neprijatelj ili power up. Ukoliko je to neprijatelj, njemu se skida odreĎena
količina energije. Ako igrač pogodi neki od power up-ova, poziva se funkcija za njegovo
aktiviranje koji ćemo videti kasnije.
Korisnički interfejs u ovoj igri je diegetic. Primer ovoga su tabla koja prikazuje
energiju igrača koja se nalazi na samoj ruci, poeni koje je igrač sakupio koji su sa leve strane
i sličice za power up-ove koje se pojavljuju iza pištolja (slika 6.2).
28
Virtuelna realnost: Osnove i izrada igara
bool isDead;
bool damaged;
VRCameraFade cameraFade;
playerAudio.clip = deathClip;
playerAudio.Play ();
playerShooting.enabled = false;
cameraFade.FadeOut (0.5f, false);
if (ScoreManager.score > MainController.topScore){
MainController.setTopScore (ScoreManager.score);
}
Invoke ("EndLevel", 1.5f);
}
}
29
Virtuelna realnost: Osnove i izrada igara
U igri postoje tri vrste pojačanja za igrača. To su pojačanje za napad, štit i lečenje
(slika 6.3). Ova pojačanja se nasumice stvaraju u polju izmeĎu četiri markera koji se nalaze
na sceni na plafonu prostorije. Pojavljuju se na razmaku izmeĎu četiri i osam sekundi i
nestaju sa scene dve sekunde nakon pojavljivanja. Ove vrednosti su podesive iz skripte kao i
iz Editora u toku igre.
Pojačanje za napad daje igraču dupli napad, što znači da nanosi duplo veću štetu
čudovištima nego inače i to traje tri sekunde. Drugo pojačanje je štit koji na tri sekunde štiti
igrača od napada čudovišta. Vreme trajanja pojačanja je podesivo. Treće pojačanje je lečenje
pri čijem sakupljanju se dopunjuje igračeva energija.
Pojačanja su regulisana uz pomoć dve skripte: PowerUpManager.cs i
PowerUpScript.cs. Sva tri objekta za pojačanja se nalaze u prefabovima i sva tri na sebi
imaju komponentu PowerUpScript.
30
Virtuelna realnost: Osnove i izrada igara
void Awake () {
PowerUpManager.powerUpIsSpawned = true;
timer = selfDestructTimer;
powerUpManager = GameObject.Find("PowerUpArea").GetComponent<PowerUpManager>();
}
void Update () {
if (timer >= 0){
timer -= Time.deltaTime;
}else{
DestroyPowerUp();
}
}
Ova skripta je veoma kratka i jasna. Pri instanciranju objekta za pojačanje na samom
početku se aktivira tajmer pri čijem će se isteku objekat uništiti. Ukoliko igrač pogodi ovaj
objekat, u zavisnosti od tipa pojačanja poziva se neka od tri funkcije iz PowerUpManagera,
tajmer se prekida i objekat uništava. Pri uništavanju objekta poziva se funkcija za stvaranje
novog iz PowerUpManager skripte.
Glavna skripta za kontrolu pojačanja je PowerUpManager.cs:
public class PowerUpManager : MonoBehaviour {
#region SPAWN_POINTS
public Transform frontLeft;
public Transform frontRight;
public Transform backLeft;
public Transform backRight;
#endregion
[SerializeField]
public GameObject[] powerUpObjects;
public Vector2 spawnTime = new Vector2(4, 8);
31
Virtuelna realnost: Osnove i izrada igara
void Awake () {
Invoke("spawnPowerUp", spawnTime.y);
atackOn = 1.0f;
shieldOn = false;
playerHealthScript = GameObject.Find("Player").GetComponent<PlayerHealth>();
playerShootingScript = GameObject.Find("ShootingPoint").GetComponent<PlayerShooting
>();
}
void Update () {
if(atackOn>1.0f && timerAtack > 0){
timerAtack -= Time.deltaTime;
}else{
timerAtack = 0;
atackOn = 1.0f;
powerUpAtackImage.color = transparent;
}
if(shieldOn && timerShield > 0){
timerShield -= Time.deltaTime;
}else{
timerShield = 0;
shieldOn = false;
powerUpShieldImage.color = transparent;
}
}
32
Virtuelna realnost: Osnove i izrada igara
atackOn = doubleDamageScale;
timerAtack = powerUpTimer;
powerUpAtackImage.color = atackColor;
}
6.3. Neprijatelji
33
Virtuelna realnost: Osnove i izrada igara
Svako od čudovišta ima svoju energiju, brzinu kretanja, raspon jačine napada, broj
poena koji donosi igraču, brzinu napada i tip specijalnog pojačanja. Sve ove vrednosti nalaze
se u skripti EnemyScript.cs koja se nalazi na prefabovima. Pored skripte svako čudovište
ima i kolajder koji registruje pogodak igrača i kada ono doĎe u dodir sa igračem.
Osim toga što postoje 3 tipa čudovišta, svako od njih moţe imati neku od četiri
specijalne moći: dvostruka energija, dvostruka šteta, ubrzano kretanje i cik-cak kretanje. Pri
instanciranju neprijatelja poziva se funkcija setSpecialType koja podešava specijalnu moć
čudovišta. Ona se poziva iz EnemyManager skripte koju ćemo videti kasnije, a kao
parametar se dodeljuje nasumice izabrana vrednost od nula do četiri. Ukoliko čudovište ima
specijalnu moć pored njegove energije se prikazuje sličica koja označava koja je moć
uključena.
public void setSpecialType(int type){
specialType = type;
switch (specialType){
case 1:
startingHealth *= 2;
currentHealth = startingHealth;
specialImage.sprite = health;
specialImage.color = new Color(1, 1, 1, 1);
break;
case 2:
atackMultiplier = 1.5f;
specialImage.sprite = atack;
specialImage.color = new Color(1, 1, 1, 1);
break;
case 3:
nav.speed *= bonusSpeed; ;
specialImage.sprite = speed;
specialImage.color = new Color(1, 1, 1, 1);
break;
case 4:
hasZigZag = true;
specialImage.sprite = zigZag;
specialImage.color = new Color(1, 1, 1, 1);
break;
}}
Svako čudovište ima odreĎenu početnu energiju koja se smanjuje kada ga igrač
pogodi. Početne energije sva tri tipa čudovišta se razlikuju. Ukoliko čudovište ima specijalnu
moć za povećanje energije, ona se duplira na početku. Kada igrač puca i pogodi objekat
čudovišta, iz njegove skripte se poziva funkcija TakeDamage koja kao parametre uzima
jačinu napada igrača i tačku u koju je čudovište pogoĎeno. Ova funkcija smanjuje energiju
čudovišta sve dok ona ne doĎe do nule. Osim toga pusta zvuk kada se čudovište pogodi, kao i
partikle koji izlaze iz njega. Kada energija čudovišta doĎe do nule, poziva se funkcija Death.
public void TakeDamage(int amount, Vector3 hitPoint){
if (isDead)
return;
enemyAudio.Play();
currentHealth -= amount;
enemyHPBar.fillAmount = currentHealth / 100f;
hitParticles.transform.position = hitPoint;
hitParticles.Play();
if (currentHealth <= 0){
Death();
}
}
34
Virtuelna realnost: Osnove i izrada igara
Funkcija Death gasi kolajder na čudovištu i pusta zvuk i animaciju za smrt čudovišta.
Tada ono počinje da tone kroz pod kako bi se sklonilo sa scene.
void Death() {
isDead = true;
capsuleCollider.isTrigger = true;
anim.SetTrigger("Dead");
enemyAudio.clip = deathClip;
enemyAudio.Play();
}
35
Virtuelna realnost: Osnove i izrada igara
void Start ()
{
StartCoroutine(spawnHelper());
36
Virtuelna realnost: Osnove i izrada igara
void Spawn ()
{
if (playerHealth.currentHealth <= 0f)
{
return;
}
Vector3 spawnPoint = bezier.getRandomPoint ();
int random = 0;
int specialType = 0;
IEnumerator spawnHelper()
{
while (true)
{
yield return new WaitForSeconds(Random.Range(spawnTime.x, spawnTime.y+1));
Spawn();
}
}
}
void Start ()
lineRendered.positionCount = numberOfPoints;
}
37
Virtuelna realnost: Osnove i izrada igara
Nakon toga unosimo ime aplikacije i završavamo proces kreiranja nove aplikacije na
konzoli. Da bi se aplikacija objavila potrebno je ispratiti osam koraka na konzoli:
Build - uploadujemo prethodno zapakovanu aplikaciju i dodajemo testere za nju.
Specs - odreĎujemo kategoriju u kojoj će se aplikacija nalaziti. Tu su i podešavanja za
internet, kontroler i mogućnost igranja više igrača.
About - u ovom delu unosimo podatke developera ili kompanije.
Content Rating - odreĎuje uzrast za koji će aplikacija biti dostupna.
Translations - ovde unosimo naslov, kratak i dugačak opis aplikacije. Osim toga
moţemo dodati jezike na koje će ova aplikacija biti prevedena.
Assets - predstavlja korak gde unosimo ikonicu, logo i reklamne slike aplikacije.
38
Virtuelna realnost: Osnove i izrada igara
Pricing - odreĎuje da li je naša aplikacija besplatna ili ne i njenu cenu ukoliko nije.
Submit - poslednji korak proverava da li su svi prethodni uslovi ispunjeni i odavde se
aplikacija šalje na proveru.
Ukoliko aplikacija proĎe proveru, biće vrlo brzo dostupna za skidanje na Oculus
storu. Ako iz nekog razloga bude odbijena, biće objašnjeno šta treba da se ispravi. Nakon
ispravke, aplikacija se ponovo šalje na proveru.
8. Zaključak
U ovom radu smo videli neke od osnovnih koncepata programiranja igre za virtuelnu
realnost. Upoznali smo se sa vrstama korisničkog interfejsa, kontrolama i načinom interakcije
korisnika sa virtuelnim svetom. Pomenuti su načini kretanja korisnika kroz svet, kao i veoma
bitna optimizacija da bi to kretanje bilo neometano. Kroz primer smo videli ceo ţivotni ciklus
jedne VR aplikacije, od njenog otvaranja na Oculusu, preko razvoja i dodavanja korisnih
servisa kao što je Firebase, do samog objavljivanja aplikacije u prodavnici. Primer je pravljen
u game engine-u Unity koji tek od skoro ima ugraĎenu podršku za izradu virtuelnih igara.
Bez sumnje Unity i Oculus će raditi na unapreĎivanju razvojnog okruţenja kao i samog
software development kit-a kako bi programerima olakšali izradu aplikacija za virtuelnu
realnost i povećali njene potencijale.
Projekat koji smo videli u ovom radu je samo zagrebao površinu mogućnosti
virtuelnih igara. Daljim radom igra se moţe proširiti dodavanjem novih neprijatelja sa novim
logikama, novih i izmenjenih nivoa gde bi igrač mogao da se naĎe u kabini neke letelice
odakle će se dalje boriti. Firebase nudi mogućnost praćenja statistike gde se moţe videti šta
se korisnicima sviĎa, a šta ne, radi unapreĎivanja igre. Na kraju, Oculus nudi mogućnost
pravljenja “soba” za više igrača gde će nekoliko prijatelja zajedno moći da učestvuju u borbi
protiv neprijatelja.
Iako savremeni ureĎaji za virtuelnu realnost još uvek nisu dovoljno rasprostranjeni i
postoje tek par godina, imaju veliki potencijal da postanu veoma korišćen posrednik za
izraţavanje, komunikaciju, edukaciju, rešavanje problema i pričanje priča. Naše bake i deke
su učile da koriste pisaće mašine. Našim roditeljima je trebalo da koriste PowerPoint
prezentacije i pretraţuju internet. Naša deca će moći da prave dvorce i teleportuju se sa
jednog na drugo virtuelno mesto. Virtuelna realnost neće zameniti pravi svet i našu ljudskost
već će je samo poboljšati.
39
Virtuelna realnost: Osnove i izrada igara
9. Literatura
40
Прилог 5/1
ПРИРОДНO - MАТЕМАТИЧКИ ФАКУЛТЕТ
НИШ
Извод, ИЗ: У овом раду смо видели неке од основних концепта програмирања
игара за виртуелну стварност. Упознали смо се са врстама корисничких
интерфејса, контролама и начином интеракције корисника са
виртуелним светом. Поменути су начини кретања корисника кроз свет,
као и врло битна оптимизација да би то било неометано. Кроз пример
смо видели цео животни циклус једне ВР апликације, од њеног
отварања на Oculus-у, преко развоја и додавања корисних сервиса као
што је Firebase, до објављивања апликације у продавници. Пример је
прављен у game engine-у Unity који тек од скоро има уграђену подршку
за израду виртуелних игара.
Датум прихватања теме, ДП:
UC 005.311.7
004.42
519.83
Holding data, HD: library
Note, N:
Abstract, AB: In this paper, we have seen some of the basic virtual reality game development
concepts. We have been acquainted with types of user interfaces, controls and
ways of interaction of the user with the virtual world. Types of movements of the
user through the world have been mentioned, as well as optimization, which is of
great importance and ensures that the movements are unobstructed. Through the
example, we have seen an entire life cycle of a VR application, from its opening in
Oculus, through the development and adding of the useful services such as
Firebase, to the application publishing on the Store. The example was developed
in Unity game engine, which has just recently obtained a built-in support for the
development of virtual games.