You are on page 1of 103

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ

НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЧЕРНІГІВСЬКА ПОЛІТЕХНІКА»

Навчально-науковий інститут електронних та інформаційних технологій


Кафедра інформаційних та комп’ютерних систем

Допущено до захисту
Завідувач кафедри
к.е.н., доцент Базилевич В.М.

«___» _________ 2020 р.

ВИПУСКНА КВАЛІФІКЦІЙНА РОБОТА


за освітньо-професійною програмою бакалавра

РОЗРОБКА FPS ГРИ НА ІГРОВОМУ РУШІЇ UNITY

Спеціальність 123 – Комп’ютерна інженерія


Галузь знань 12 – Інформаційні технології

Виконавець:
студент гр. КІ–161
Вачнадзе Анна-Марія Олександрівна
(підпис)

Керівник:
професор
–––––––––––––––––––––––––––––
д.т.н., професор
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

(посада) (науковий ступінь, вчене звання)

Зайцев Сергій Васильович


(підпис)

Чернігів 2020
2

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ


НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЧЕРНІГІВСЬКА ПОЛІТЕХНІКА»

Навчально-науковий інститут електронних та інформаційних технологій


Кафедра інформаційних та комп’ютерних систем

ЗАТВЕРДЖУЮ:
Зав. кафедри
к.е.н., доцент Базилевич В.М.

“____” ___________2020г.

ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
НА ВИПУСКНУ КВАЛІФІКАЦІЙНУ РОБОТУ
ЗДОБУВАЧА ВИЩОЇ ОСВІТИ
ЗА ОСВІТНЬО-ПРОФЕСІЙНОЮ ПРОГРАМОЮ БАКАЛАВРА

Вачнадзе Анни-Марії Олександрівни

Тема роботи: РОЗРОБКА FPS ГРИ НА ІГРОВОМУ РУШІЇ UNITY

Тему затверджено наказом ректора


від "__"_____________ 2020 р. №________

1. Вхідні дані до роботи:


Джерела в області відеоігор, технічна документація ігрових рушіїв,
ігровий рушій Unity, тривимірні моделі, графічні текстури, звукові доріжки.
2. Зміст розрахунково-пояснювальної записки :
Кваліфікаційна робота складається зі вступу, основної частини та висновків.
Основна частина складається із трьох розділів: «Аналіз ігор»,
«Проектування гри» та «Розробка гри».
3. Демонстраційні матеріали:
17 слайдів презентації роботи
3

4. Календарний план
№ Назва етапів роботи Термін виконання Примітки
1 Визначення з керівником 27.01.2020
2 Визначитися з темою роботи 20.01.2020
3 Індивідуальне завдання 3.02.2020
4 Знайомство з проблемою,
інформаційними джерелами, аналіз 20.03.2020
існуючих рішень.
5 Прийняття рішень стосовно основних
10.04.2020
моментів розробки
6 Звіт з першої частини роботи (ІЗ, Вступ
24.04.2020 Звіт
та аналіз задачі)
7 Збори з питань практики 08.05.2020
8 Розробка системи 15.05.2020
9 Звіт з практики, розділ розробка 17.05.2020 Звіт
10 Реалізація системи 24.05.2020
11 Попередній захист 29.05.2020
12 Перевірка на «плагіат» 12.06.2020
13 Рецензування роботи 12.06.2020
14 Захист кваліфікаційної роботи 16.06.2020

Завдання підготував:
керівник Зайцев Сергій Васильович
(підпис)
«___» _________ 2020 р.
Завдання одержав:
студент Вачнадзе Анна-Марія Олександрівна
(підпис)
«___» _________ 2020 р.
4

РЕФЕРАТ

Кваліфікаційна робота, 100 с., 43 рис., 29 джерел, 1 додаток.

Тема кваліфікаційної роботи – розробка FPS гри на ігровому рушії Unity.


Об’єкт дослідження – процес створення гри на безкоштовному рушії гри.
Предмет дослідження є гра для операційної системи Windows. Гра була
розроблена за допомогою ігрового рушія Unity, який працює на таких платформах
як Windows, Linux, MacOS. Unity - зручний і практичний інструмент для розробки
комп’ютерних, мобільних ігор і т.д. Окрім цього він став популярним
інструментом серед кіно-та автоіндустрії.
Мета дослідження:
- ознайомлення з інструментом розробки комп’ютерних, мобільних та
інших додатків Unity;
- розробка десктопної гри для операційної системи Windows;
- продемонструвати можливості та доступність рушія гри Unity.
За останні 20 років ігрова індустрія стала доволі великою, впливовою та
фінансово вигідною. Збільшилася кількість пристроїв на яких можливо запустити
ігри: комп’ютери, ноутбуки, смартфони, планшети, звичайні та портативні ігрові
консолі. З часом стали доступні різні ігрові рушії, завдяки яким будь-хто міг
створювати ігри самостійно, оскільки раніше розробникам доводилося власноруч
створювати інструменти для розробки ігор. Серед таких рушіїв був Unity, за
допомогою якого була створена дана кваліфікаційна робота.

UNITY, C#, WINDOWS, LINUX, MACOS


5

THE ABSTRACT

Qualification work, 100 pp. 43 fig., 29 sources, 1 appendix.

The topic of the qualification work is development of FPS game on the Unity
game engine.
The object of research is the process of creating a game on a free game engine.
The subject of the study is a game for the Windows operating system. The game
was developed by using Unity game engine, which runs on platforms such as Windows,
Linux, MacOS. Unity is a convenient and practical tool for developing computer and
mobile games, etc. In addition, it has become a popular tool among the film and
automotive industries.
The purpose of the study:
- introduction to the tool for developing computer, mobile and other Unity
applications;
- development of a desktop game for the Windows operating system;
- demonstrate the capabilities and availability of the Unity game engine.
Over the last 20 years, the gaming industry has become quite large, influential
and financially profitable. The number of devices that can run games has increased:
computers, laptops, smartphones, tablets, regular and portable game consoles. Over
time, various game engines became available, thanks to which anyone could create
games on their own, as previously developers had to create their own tools for creating
games. Among such engines was Unity, with the help of which this qualifying work
was created.

UNITY, C#, WINDOWS, LINUX, MACOS


6

ЗМІСТ

ВСТУП.................................................................................................................10

1 АНАЛІЗ ІГОР...................................................................................................11

1.1 КЛАСИФІКАЦІЯ ІГОР....................................................................................11


1.1.1 Класифікація ігор за жанром........................................................11
1.1.1.1 Action (Бойовик)........................................................................11
1.1.1.2 Adventure (Пригодницькі)........................................................12
1.1.1.3 Action-adventure (Пригодницький бойовик)...........................13
1.1.1.4 Role-playing (Рольові)...............................................................14
1.1.1.5 Simulation (Симулятори)...........................................................15
1.1.1.6 Strategy (Стратегії)....................................................................16
1.1.1.7 Sports (Спортивні).....................................................................16
1.1.2 Класифікація ігор за кількістю користувачів.............................17
1.1.2.1 Single-player (Однокористувацькі)..........................................17
1.1.2.2 Cooperative (Кооперативні)......................................................17
1.1.2.3 Multiplayer (Багатокористувацькі)...........................................18
1.2 ЖАНР «ШУТЕР»......................................................................................18
1.2.1 Шутер від першого особи (FPS)...................................................19
1.2.1.1 Означення...................................................................................19
1.2.1.2 Дизайн гри..................................................................................19
1.2.1.3 Боротьба та лікування...............................................................20
1.2.1.4 Дизайн рівнів.............................................................................21
1.2.2 Відомі приклади шутерів..............................................................22
1.2.2.1 Серія Doom................................................................................22
1.2.2.2 Серія Crysis................................................................................24
1.2.2.3 Серія Half-Life...........................................................................27

2 ПРОЕКТУВАННЯ ГРИ................................................................................31
7

2.1 ВИБІР ІГРОВОГО РУШІЯ...........................................................................31


2.1.1 Ігрові рушії..........................................................................................31
2.1.1.1 Unity............................................................................................31
2.1.1.2 Unreal Engine..............................................................................34
2.1.1.3 CryEngine...................................................................................37
2.1.2 Порівняння рушіїв..............................................................................39
2.1.2.1 Мова програмування.................................................................40
2.1.2.2 Доступнісь матеріалів...............................................................40
2.1.2.3 Ціна.............................................................................................42
2.1.2.4 Висновки....................................................................................42
2.2 ІГРОВИЙ РУШІЙ UNITY............................................................................43
2.2.1 Загальна інформація...........................................................................43
2.2.2 Знайомство з інтерфейсом.................................................................43
2.2.2.1 Вікно проекту............................................................................44
2.2.2.2 Перегляд сцени..........................................................................45
2.2.2.3 Вікно ієрархії.............................................................................46
2.2.2.4 Вікно інспектора........................................................................46
2.2.2.5 Панель інструментів.................................................................47
2.3 ВИБІР ДОДАТКОВИХ ІНСТРУМЕНТІВ ТА НЕОБХІДНИХ МАТЕРІАЛІВ........48
2.3.1 Моделі та текстури........................................................................48
2.3.2 Обробка зображень........................................................................48
2.3.3 Звукове оформлення......................................................................48
2.3.4 Плагіни...........................................................................................48
2.3.5 Текстовий редактор.......................................................................48
2.3.6 Відеоматеріали для навчання.......................................................49

3 РОЗРОБКА ГРИ.............................................................................................50

3.1 РЕАЛІЗАЦІЯ КЛАСІВ.................................................................................50


3.1.1 A001Spider.cs.................................................................................50
3.1.2 A002Door.cs....................................................................................50
8

3.1.3 AmmoPickup.cs...............................................................................50
3.1.4 AmmoPickupSMG.cs......................................................................50
3.1.5 BarrelBang.cs..................................................................................50
3.1.6 BarrelBlow.cs..................................................................................50
3.1.7 CaveDoor.cs....................................................................................51
3.1.8 CaveDoorExit.cs..............................................................................51
3.1.9 CreackyDoorOpen.cs.......................................................................51
3.1.10 CredToMenu.cs...............................................................................51
3.1.11 CrossAnimate.cs..............................................................................51
3.1.12 CutScene01.cs.................................................................................51
3.1.13 EnemyScript.cs................................................................................51
3.1.14 EnemyScriptSpider.cs.....................................................................52
3.1.15 GameOverToMenu.cs.....................................................................52
3.1.16 GlobalAmmo.cs...............................................................................52
3.1.17 GlobalHealth.cs...............................................................................52
3.1.18 GlobalScore.cs.................................................................................52
3.1.19 GunFire.cs.......................................................................................52
3.1.20 GunFireSMG.cs...............................................................................53
3.1.21 HandGunDamage.cs........................................................................53
3.1.22 HandGunReload.cs..........................................................................53
3.1.23 HealthMonitor.cs.............................................................................53
3.1.24 MainMenuOptions.cs......................................................................53
3.1.25 OpenDoor001.cs..............................................................................53
3.1.26 PauseGame.cs..................................................................................54
3.1.27 PickUp9mm.cs.................................................................................54
3.1.28 PickUpSMG.cs................................................................................54
3.1.29 PlayerCasting.cs..............................................................................54
3.1.30 RespawnLevel.cs.............................................................................54
3.1.31 SkyRotation.cs.................................................................................54
3.1.32 SMGReload.cs.................................................................................55
9

3.1.33 SniperScopeActive.cs......................................................................55
3.1.34 SpiderFollow.cs...............................................................................55
3.1.35 SpiderScore.cs.................................................................................55
3.1.36 SplashToMenu.cs............................................................................55
3.1.37 WeaponSwitch.cs............................................................................55
3.1.38 ZombieFollow.cs.............................................................................56
3.1.39 ZombieScore.cs...............................................................................56
3.1.40 ZScore25.cs.....................................................................................56
3.1.41 ZScore50.cs.....................................................................................56
3.1.42 ZScore100.cs...................................................................................56
3.2 РЕАЛІЗАЦІЯ ДИЗАЙНУ РІВНІВ..................................................................56
3.3 РЕАЛІЗАЦІЯ ІНТЕРФЕЙСУ КОРИСТУВАЧА................................................59
3.3.1 Головний інтерфейс......................................................................59
3.3.2 Меню паузи....................................................................................62
3.3.3 Головне меню.................................................................................63
3.4 ВИСНОВКИ...............................................................................................65

ВИСНОВКИ.........................................................................................................66

ПЕРЕЛІК ВИКОРИСТАНИХ ДЖЕРЕЛ...........................................................67

ДОДАТКИ............................................................................................................70

ДОДАТОК А........................................................................................................72
10

ВСТУП

Комп’ютерні ігри за останні 20-30 років стали невід’ємною частиною життя


кожного з нас. Не важливо на чому ми граємо: на домашньому комп’ютері, на
телефоні під час подорожі на роботу або в черзі до лікаря, на планшеті під час
шкільної перерви або на консолі під час поїздки за кордон.
Технічний прогрес другої половини минулого століття дав можливість
розвитку нової індустрії – ігрової. Вона стала шансом для багатьох талановитих
людей знайти себе, показати на що вони здатні, серед них програмісти,
художники, музиканти. Для звичайних людей ігри стали можливістю відпочити
від повсякденного життя, поринути у нові світи, які існують лише у цифровому
просторі.
Нині технічний прогрес для багатьох асоціюється з прогресом в індустрії
ігор. Це твердження не далеке від істини. Ігрові студії намагаються вразити
деталізацією моделей та фотореалістичністю текстур, правдоподібною фізикою та
взаємодією персонажа гри з навколишнім середовищем. Ці самі технології
використовуються надалі в кіноіндустрії для створення реалістичних спецефектів
та сцен, які з певних причин неможливо відтворити у реальному житті.
Завдяки доступним інструментам розробки ігор кожен має можливість
сьогодні створити гру не лише в команді а й самому. Серед них популярні Unreal
Engine, CryEngine та Unity. Метою даного проекту є створення гри у жанрі FPS
(First Real Person) для демонстрації можливостей ігрового рушія Unity та
доступності розробки власної гри.
11

1 АНАЛІЗ ІГОР

1.1 Класифікація ігор

1.1.1 Класифікація ігор за жанром

Гра може містити собі як один так і ознаки кількох жанрів. Незважаючи на
це, існує чітка класифікація жанрів відеоігор [1]. Нижче наведені лише основні.

1.1.1.1 Action (Бойовик)

Вимагає від гравця певних фізичних зусиль, таких як швидкості реакції та


здібності швидко приймати тактичні рішення. Дія таких ігор відбувається дуже
динамічно і потребує більшою мірою рефлексів, ніж логіки і планування.
Позначення жанру гри як «action» відносно рідко використовується без
доповнення, оскільки це поняття дуже широке і ним можна схарактеризувати
більшу частину всіх створених ігор. У цю категорію потрапляють платформери,
шутери, файтинги, стелс ігри, баттл-роялі, ритмічні ігри, тощо [2].
Приклади ігор: Super Mario Bros, Doom, Mortal Kombat, Metal Gear,
Fortnite, Guitar Hero (Рисунок 1.1).

Рисунок 1.1 – Приклад action гри (Super Mario Bros)


12

1.1.1.2 Adventure (Пригодницькі)

В основі ігрового процесу інтерактивна історія, рушієм якої є дослідження


та вирішення головоломок. Зосередженість жанру на сюжеті дозволяє йому
значною мірою черпати з інших засобів масової інформації, літератури та фільмів,
що базуються на оповіді, охоплюючи найрізноманітніші літературні жанри.
Багато пригодницьких ігор (текстових та графічних) розраховані на одного гравця
[3].
Деякі субжанри: нарративні пригодницькі ігри, симулятори пересування
(walking simulators), інтерактивне кіно.
Приклади ігор: The Stanley Parable, Death Stranding, Detroit: Become Human
(Рисунок 1.2).

Рисунок 1.2 – Приклад adventure гри (Detroit: Become Human)


13

1.1.1.3 Action-adventure (Пригодницький бойовик)

Поєднує ознаки пригодницьких та екшн ігор. Зазвичай пригодницькі ігри


мають для гравця ситуаційні проблеми, які мають вирішити, дуже мало або
взагалі не мають дій. Якщо є дія, вона, як правило, обмежується ізольованими
міні-іграми. Екшн ігри мають геймплей, який заснований на взаємодії в режимі
реального часу, яка кидає виклик рефлексам. Тому екшн-пригодницькі ігри
залучають як рефлекси, так і вирішення проблем, як у жорстоких, так і в
ненасильницьких ситуаціях [4].
Деякі субжанри пригодницького бойовика: екшн-пригодницька гра від
першого обличчя (first-person action-adventure), екшн-пригодницька гра від
третього обличчя (third-person action-adventure), імерсивна симуляція (immersive
sim), стелс гра, сурвайвел-горор (survival horror).
Приклади ігор: Far Cry, Grand Theft Auto, S.T.A.L.K.E.R, Splinter Cell,
Resident Evil (Рисунок 1.3).

Рисунок 1.3 – Приклад action-adventure гри (Star Wars Jedi: Fallen Order)
14

1.1.1.4 Role-playing (Рольові)

Частіше цей жанр називають просто RPG. Гравець контролює дії одного
або кількох персонажів. Механіки та терміни цього жанру перекочували з
настільних рольових ігор по типу Dungeons & Dragons. Персонажі зростають у
силі та здібностях, які розробляє гравець. Рольова гра рідко кидає виклик фізичній
координації гравця або часу реакції. Ігри покладаються на добре розвинену
історію та навколишній світ. Рольові відеоігри зазвичай намагаються
запропонувати більш складні та динамічні взаємодії з персонажами, ніж ті, що є в
інших жанрах відеоігор. Зазвичай це передбачає додатковий фокус на штучному
інтелекті та сценарії поведінки персонажів, що не керуються комп'ютером,
керованими комп'ютером [5].
Деякі субжанри: рольовий бойовик (action RPG), рольова пісочниця
(sandbox RPG), масова багатокористувацька онлайнова рольова гра (Massively
multiplayer online role-playing games, MMORPG).
Приклади ігор: Diablo, Minecraft, Lineage II (Рисунок 1.4).
15

Рисунок 1.4 – Приклад role-playing гри (Minecraft із використанням шейдерів


Sildur's Vibrant shaders v1.27 Lite)
1.1.1.5 Simulation (Симулятори)

Особливість жанру – якомога точніше відтворення реальності, її законів


фізики, властивостей предметів, процесів та подій. Зазвичай у грі немає чітко
визначених цілей, а гравцю натомість дозволяється вільно керувати персонажем
чи оточенням. Подібні ігри фокусуються на одному об’єкті або явищі, що дуже
корисно для тих, хто бажає вивчити певну тему (наприклад медична, спортивна
або технічна тема). Окрім цього є і просто ігри для розваг, наприклад серія “Sims”
або популярні у минулому Тамагочі [6].
Деякі субжанри: медичні симулятори, військові симулятори, «Сім» ігри
(“Sim” games), симулятори транспорту.
Приклади ігор: Trauma Center, Steel Panthers, Sims 4, Euro Truck Simulator
(Рисунок 1.5).

Рисунок 1.5 – Приклад simulation гри (The Sims 4)


16

1.1.1.6 Strategy (Стратегії)

Гра фокусується на вміле мислення та планування для перемоги. Гравець


повинен спланувати ряд дій проти одного або декількох опонентів. Елемент
випадковості грає малу роль. В більшості стратегіях гравцеві надається
богоподібний погляд на ігровий світ і опосередковано контролює ігрові одиниці
під своїм управлінням. Таким чином, стратегічні ігри можуть мати в собі
елементи ведення війни та можливість розвивати економіку чи керувати
політикою [7].
Деякі субжанри: Багатокористувацька онлайнова бойова арена (MOBA),
стратегія в реальному часі (RTS), покрокова стратегія.
Приклади ігор: Dota 2, Dungeon Keeper, Heroes of Might and Magic
(Рисунок 1.6).

Рисунок 1.6 – Приклад strategy гри (Heroes of Might and Magic III)

1.1.1.7 Sports (Спортивні)


17

Ігри подібного жанру імітують заняття спортом. Можна управляти як


одним гравцем, так і цілою командою. Протилежний гравець чи команда
контролюється іншим гравцем або штучним інтелектом [8].
Деякі субжанри: гонки, спортивні, спортивні бійки.
Приклади ігор: Grand Turismo, FIFA, UFC (Рисунок 1.7).

Рисунок 1.7 – Приклад sports гри (Grand Turismo Sport)

1.1.2 Класифікація ігор за кількістю користувачів

Як у випадку з жанрами, гра може мати кілька режимів гри. Можна грати як
поодинці, так и з декількома людьми.

1.1.2.1 Single-player (Однокористувацькі)

Розраховані на гру одним користувачем. Опонентом в такому випадку


проти гравця буде комп’ютер [9].
Приклад ігор: Dead Space, Space Rangers, Dishonored, Resident Evil.
18

1.1.2.2 Cooperative (Кооперативні)

В таких іграх є можливість грати в одній команді з іншим гравцем або зі


штучним інтелектом. Зазвичай навколишнє середовище та механіка створені
таким чином, що користувач не може пройти гру без допомоги комп’ютера в ролі
другого гравця або іншої людини. Дуже рідко виходять ігри, де геймплей лише
кооперативний [10].
Приклад ігор: Half-Life: Decay, Dead Space 3, FEAR 3, Dungeon Siege III.

1.1.2.3 Multiplayer (Багатокористувацькі)

Розраховані на гру для двох и більше користувачів. Гравці можуть бути як в


одній локальній мережі, так і в різних частинах світу. Таким чином вашим
противником або товаришем по команді буде справжня людина. Частіше при
слові «багатокористувацька» ми уявляємо ігрову сесію на десятки на певній
локації [11].
Приклад ігор: Counter-Strike, Call of Duty, World of Warcraft, EVE Online.

1.2 Жанр «Шутер»

Шутер (від англійського shooter – «стрілець») — піджанр , який перевіряє


просторову обізнаність гравця, рефлекси та швидкість в середовищі. Шутер
охоплює багато піджанрів, які мають спільну рису зосередження уваги на діях
гравця, що вступає в бій зі зброєю проти ворогів, якими керує штучний інтелект,
та ворогами, якими виступають інші гравці.
Зазвичай зброя є вогнепальною або якоюсь іншою зброєю дальньої
дальності і її можна використовувати в поєднанні з іншими інструментами,
такими як гранати для непрямого враження, броні для додаткової оборони або
аксесуари, такі як телескопічні приціли, щоб змінити вигляд зброї. Поширений
19

ресурс, який зустрічається у багатьох ігрових шутерах - це боєприпаси, броня чи


здоров'я, або оновлення, які посилюють зброю персонажа гравця.
Найчастіше мета гри - стріляти в супротивників і проходити місії, щоб
персонаж внаслідок дій гравця не гинув чи вмирав . Шутер - це жанр відеоігри, де
фокус майже повністю на ураженні ворогів персонажа за допомогою зброї,
наданої гравцеві [12].
1.2.1 Шутер від першого особи (FPS)
Шутер від першої особи (FPS) - це жанр відеоігор, зосереджений на зброї та
інших битвах на основі озброєння з точки зору від першої особи. Гравець
переживає дію очима головного героя. Жанр поділяє загальні риси з іншими
шутерськими іграми, що, в свою чергу, змушує підпадати під розділ екшн-гри. З
моменту створення жанру вдосконалена 3D-та псевдо-3D графіка кинули виклик
розробці обладнання, а багатокористувацькі ігри стали невід'ємною частиною
[13].

1.2.1.1 Означення

Шутери від першої особи - це різновиди шутерів, які характеризуються


точкою зору від першої особи, за допомогою якої гравець бачить дію очима
персонажа гравця. Вони на відміну від шутерів третьої особи, в яких гравець
може бачити (як правило, ззаду) персонажа, яким вони керують. Основним
елементом є бойові дії, в основному з вогнепальною зброєю.
Шутери від першого особи також часто класифікуються як відмінні від
шутерів з легкою зброєю, схожий жанр із перспективою від першої особи, який
використовує периферійні пристрої з легкої зброї, на відміну від шутерів від
першої особи, які використовують звичайні пристрої введення для руху. Ще одна
відмінність полягає в тому, що шутери з легкою зброєю від першої особи, такі як
Virtua Cop, часто мають рух “по рейках” (сценарій), тоді як шутери від першої
особи, такі як Doom, дають гравцеві більше свободи для пересування.
20

1.2.1.2 Дизайн гри

Як і в більшості ігор-шутерів, шутери від першої особи мають аватар, одна


або більше зброї дальнього ураження і різну кількість ворогів. Оскільки вони
відбуваються в 3D-середовищі, ці ігри, як правило, дещо реалістичніші, ніж 2D-
шутер, і мають більш точні уявлення про гравітацію, освітлення, звук та
зіткнення. Шутери від першої особи, в які грають на персональних комп’ютерах,
найчастіше керуються комбінацією клавіатури та миші. Ця система вважається
вищою за ту, що зустрічається в консольних іграх, які часто використовують два
аналогових стіка: один, який використовується для бігу та кроку у бік, а другий
для огляду та прицілювання. На екрані зазвичай відображаються руки та зброя
персонажа, дані про стан здоров'я, боєприпаси та місцезнаходження. Часто можна
накласти карту навколишньої місцевості [13].

1.2.1.3 Боротьба та лікування

Шутери від першої особи часто зосереджуються на ігрових діях зі


швидкими та кривавими перестрілками, хоча дещо більше уваги приділяється
загадці, вирішенню проблем та логічним задачам. Окрім стрільби, також може
широко застосовуватися боротьба з ближнім боєм. У деяких іграх зброя
ближнього бою особливо потужна - винагорода за ризик, який повинен взяти
гравець, маневруючи своїм персонажем в безпосередній близькості до ворога. В
інших ситуаціях зброя ближнього бою може бути менш ефективною, але
необхідною в крайньому випадку. "Тактичні шутери" є більш реалістичними та
потребують командної роботи та стратегії, щоб досягти успіху; гравець часто
командує загоном персонажів, якими може керувати гра чи люди-товариші по
команді.
Шутери від першої особи зазвичай дають гравцям вибір зброї, яка має
великий вплив на те, як гравець підійде до гри. Деякі ігрові конструкції мають
реалістичні моделі фактично існуючої або історичної зброї, включаючи їхню
21

величину вогню, розмір магазину, кількість боєприпасів, віддачу та точність. Інші


ігри для шутерів від першої особи можуть включати образні варіанти зброї, в
тому числі прототипи зброї майбутнього, озброєння, визначене сценарієм "чужої
технології" та/або використовувати широкий набір снарядів, від промислових
трудових інструментів до лазерних, енергетичних, плазмових, ракетних та
гранатометів або арбалетів. Ці варіації також можуть бути застосовані до анімації
гранат. Крім того, більш нетрадиційні способи руйнування можуть бути
використані з рук видимих користувачів, такі як полум'я, електрика, телекінез або
інші надприродні сили. Однак дизайнери часто дозволяють персонажам носити
різні кратні озброєння з невеликим або незначним скороченням швидкості чи
рухливості, або, можливо, більш реалістично, пістолетом чи меншим пристроєм
та довгою гвинтівкою або навіть обмеженням гравця лише однією зброєю
одночасно. У більшості ігор часто є варіанти торгівлі, оновлення або заміни.
Таким чином, стандарти реалізму різняться між елементами дизайну. В
основному головного героя можна зцілити і переозброїти за допомогою
предметів, таких як аптечки, просто проходячи по них. Деякі ігри дозволяють
гравцям накопичувати бали досвіду, які схожі на ті, що існують в рольових іграх і
можуть розблокувати нову зброю та здібності [13].

1.2.1.4 Дизайн рівнів

Шутер від першої особи можуть бути структурно складені з рівнів, або
використовувати техніку суцільної розповіді, в якій гра ніколи не залишає
перспективи від першої особи. Інші містять великі середовища з пісочницею, які
не поділяються на рівні і можуть вільно досліджуватися. У шутерів від першої
особи герої взаємодіють із оточуючим середовищем в різній мірі, від основ, таких
як використання дверей, до вирішення задач на основі різноманітних
інтерактивних об'єктів. В деяких іграх гравець може завдати шкоди
навколишньому середовищу різною мірою. Наприклад використання бочок, що
містять вибухонебезпечний матеріал, в який гравець може вистрілити і тим самим
22

завдати шкоди собі та ворогам ворогам, що знаходяться поблизу. В інших іграх є


середовища, які є руйнівними, що забезпечує додаткові візуальні ефекти. Ігровий
світ часто використовує наукову фантастику, історичну (особливо Другу світову
війну) або сучасну військову тематику, з такими антагоністами, як прибульці,
монстри, терористи та солдати різних типів. Ігри мають кілька рівнів складності;
у більш жорстких режимах вороги агресивніші та завдають більше шкоди, а
кількість спорядження обмежено. У більш легких режимах гравець може досягти
успіху через час реакції; на більш складних налаштуваннях часто потрібно
запам'ятовувати рівні шляхом проб і помилок.

1.2.2 Відомі приклади шутерів

1.2.2.1 Серія Doom

У 1991 році Джон Кармак та Джон Ромеро покинули “Softdisk” та заснували


власну ігрову студію під назвою “id Software”. Перша частина серії, яка вийшла у
1992 році була проривом.
Оскільки в той час не було справжньої 3D графіки, то в грі було вперше
використано бінарне розбиття простору [14,15]. Суть полягає у тому, що
середовище розбивається на зручні для обробки рушієм гри частини. Процесор
ходить по дереву даних і відрисовує кожен сектор (ноду в дереві). Далі цю
процедуру проходить найближча нода до попередньої. Таким чином системі було
простіше відображати середовище а в грі був ефект різних висот. Тому незалежно
від того де був ворог, вище чи нижче головного героя, достатньо було вистрілити
в сторону ворога і він отримував поранення (див. Рисунок 1.8).
23

Рисунок 1.8 – Приклад ілюзії різних висот при бінарному розбитті простору
Система освітлення ґрунтувалася безпосередньо на коригуванні кольорової
палітри поверхонь: замість того, щоб обчислювати, як світло переміщалося від
джерел світла до поверхонь, використовуючи трасування променів, гра обчислює
"рівень світла" невеликого відрізка рівня виходячи з його відстані від світла
джерела. Потім воно змінює кольорову палітру поверхневих текстур цього
розділу, щоб імітувати, як темно це буде виглядати [16].
Гра була створена з рівнів, група яких разом називалися епізодами.
Фінальний рівень був босфайтом з дуже сильним ворогом. Самі вороги були 2D
спрайтами. На рівнях вони нападали групами. Окрім ворогів небезпечними були
елементи рівнів, такі як токсичні відходи, стеля, яка могла падати. По всіх рівнях
була зброя, патрони, броня, аптечки, ключові предмети, без яких не було
можливості просуватися далі. Також були бустери, які тимчасово давали різні
ефекти, від швидкості до режиму «берсерка».
Окрім режиму одиночної гри, було два режими мультиплеєру –
кооперативний на 4 гравця в локальній мережі, коли можна було пройти гру
разом та “deathmatch”, в якому 4 гравці билися один проти одного.
Сюжет, який був на той час простим для розуміння, розповідав про
безіменного піхотинця (в серії його називають Doomguy, Doom Marine і
віднедавна Doom Slayer), який намагається вижити під час вторгнення демонів
24

через портальні ворота на Фобосі та Деймосі. Надалі сюжетна арка персонажа


продовжується у Doom II.
Серед усієї франшизи Doom 3 виглядає дуже дивно не тільки через те, що це
мав бути ребут франшизи. На той час Кармак хотів показати можливості ігрового
рушія «Id Tech 4», в якому дуже реалістично показані світло та тіні. Але спроба
показати переваги нових технологій провалилася: гра була занадто темною, ліхтар
розряджався та не було можливості носити його одночасно зі зброєю. Рівні вже не
були відкритими яка раніше, тепер вони були темними коридорами з ворогами за
дверима для ефекту горору (Рисунок 1.9).

Рисунок 1.9 – Можливості реалістичного відображення світла та тіні


ігровим рушієм «Id Tech 4». Спроба показати кращі сторони нових технологій
зробила гру занадто темною для проходження.

Перезавантаження франшизи в 2016 році повернулося до витоку франшизи


як в дизайні рівнів та механіці битв, так і в плані сюжету. Окрім звичного
“Deathmatch” був запроваджений редактор рівнів SnapMap, що дозволяло грати по
мережі на власних картах та картах гравців. Також нова гра мала підтримку VR –
але не без проблем, бо гра не була з самого початку розроблена для шоломів
віртуальної реальності. Камеру гравця дуже сильно трусило через фізику, не
оптимізовану для гри стоячи.
25

1.2.2.2 Серія Crysis

Перша частина побачила світ у 2007 році. Компанія “Crytek” була на той час
відома як розробник першої частини Far Cry та ігровим рушієм CryEngine. В новій
грі було показано переваги CryEngine 2, для якого і було створено Crysis.
Розробники намагалися показати неперевершену графіку, що, нажаль, означало
неможливість запустити гру на більшості комп’ютерах того часу. Глибина
різкості, м’які частинки, об’ємне світло (Рисунок 1.10), симуляція води на візорі –
все це потребувало ресурсів [17].

Рисунок 1.10 – Приклад об’ємного світла у грі

Затінення навколишнього світла у екранному просторі або ж SSAO - техніка


наближеного розрахунку ambient occlusion на основі згенерованої у екранних
координатах інформації. Саме в Crysis було вперше продемонстровану дану
розробку. Світло з навколишнього середовища (пряме освітлення, що було
розсіяне і відбите геометрією у випадкових напрямках) покриває сцену
неоднаково. Це відбувається через те, що деякі області затінюють від непрямого
26

освітлення сусідні ділянки (стики між цеглою, стінами, глибокі впадини і виступи
на поверхні, тощо).
Характерна риса SSAO - це розрахунок ambient occlusion у екранних
координатах (screen space), що робить метод придатним для роботи з
зображенням тривимірної сцени у реальному часі, в певній мірі як пост-обробки.
Класичний підхід базується на буфері глибини сцени, який часто генерують
попередньо, ще до остаточного розрахунку освітлення. Знаючи глибину кожного
фрагмента (пікселя) - можна з певною точністю розрахувати наскільки сусідні
фрагменти затінюють його від навколишнього світла (Рисунок 1.11) [18].

Рисунок 1.11 – Приклад сцени без SSAO та з SSAO (на прикладі Half-Life
2)

Не зважаючи на усі проблеми із запуском гри, серія стала однією з


найкращих і найпопулярніших. Гравець міг взаємодіяти із середовищем: ламати
стіни будівель, хапати предмети і кидати їх у ворогів, їздити на машинах для
подолання великих відстаней на карті, дерева падали у напрямку куди стріляв у
них гравець [17].
27

Рисунок 1.12 – Приклад взаємодії із середовищем: гравець може ухопити


ворога під час сутички (режим броні)
Сюжет гри розповідає про військову операцію американського
спецпідрозділу, особливістю якого була броня – нанокостюм. Даний нанокостюм
мав кілька режимів: сила, невидимість швидкість, броня. Використання кожного з
режимів допомагало в проходженні гри без проблем. Одразу після початку нас
знайомлять не тільки із звичними ворогами людьми але й із представниками
інопланетної раси. Нажаль зустріч з прибульцями позбавляє команду двох бійців.
Елементи наукової фантастики дуже гарно поєднуються із тривіальною історією
про добрих та поганих військових різних країн. Серед озброєння крім звичних для
гравця пістолета та гвинтівок були мініган та інопланетний молекулярний
акселератор.
Загалом кожна частина серії була проривом в графічних технологіях та
навіть сьогодні тестування нового комп’ютера не обійдеться без результатів в
будь-якій частині Crysis.

1.2.2.3 Серія Half-Life


28

В далекому 1996 році двоє колишніх працівники Microsoft Гейб Ньюел та


Майк Харрінгтон заснували компанію Valve. Одним з перших проектів стала
перша Half-Life.
В той час цілісні історії в FPS майже не існували. Гравцю давали коротку
довідку та контекст а потім кидали по різним рівням винищувати ворогів.
В інших жанрах коли гра оберталася навколо історії, розповідь значною
мірою показувалася через бульбашки тексту та катсцени – відеосцени всередині
гри. Тому коли Half-Life почалася зі сцени у вагоні монорельси – це був прорив
(Рисунок 1.13).

Рисунок 1.13 – Перша сцена гри – прорив у жанрі FPS

Гравець міг бути частиною світу. Замість того щоб дивитися сцену, він міг
пересуватися в місцевості, в той час як історія розгорталася навколо персонажа. У
поєднанні з перспективою від першого обличчя, гравці мали відчуття присутності
в подіях.
До Half-Life дизайн рівнів в багатьох FPS ігор був схожий на дизайн в
аркадних іграх. Потрібно було пройти рівень для доступу до наступного. Рідко
29

коли переміщення між ними було логічним. Тому ігри минулого рідко
переймалися реалізмом, фокус був на геймплеї.
У Half-Life розробники намагалися створити реалістичний світ, який
можливо було досліджувати. Переміщення між рінями було логічним, воно
поєднувало оточуюче середовище з історією. Завантаження нового рівня було
непомітним, його видавало лише назва нової глави на екрані або зупинка гри на
кілька секунд та надпис “Loading…”. Світ гри був ніби без швів [19] (Рисунок
1.14).

Рисунок 1.14 – Приклад завантаження нового рівня

Ще одним проривом був штучний інтелект. У минулому алгоритм ворогів


був простим – якщо вони бачать гравця, то вони його атакують. В Half–Life була
можливість ховатися за укриттям, утворювати групи, кидати гранати. Такі
впровадження робили сутички живими та захоплюючими.
Дружні до гравця неігрові персонажі могли допомагати під час
проходження: охоронці могли відстрілювати ворогів, вчені могли дати доступ до
30

певних приміщень або підлікувати головного героя, якщо він отримає тяжке
поранення. Усе це робило світ гри біль живим та правдоподібним [19].
Сюжет розповідав про аварію в науковому комплексі «Чорна Меза», яка
відбулася у наслідок вибуху кристалу із транзитного світу Зен. З цього моменту
головний герой, Гордон Фрімен, намагається врятувати себе і разом з тим
зачинити портал, який підтримується невідомою істотою на іншій стороні
порталу.
Ворогами для гравця будуть як і прибульці, так і звичайні солдати зі
спецпідрозділами, завданням яких є винищення будь-яких ознак інциденту, у
тому числі знищення персоналу «Чорної Мези».
Half-Life 2 була не менш проривною для ігрової індустрії. Раніше будь-який
об’єкт був нерухомим, або рухався за скриптом. Valve запровадила можливість
взаємодії з будь-яким елементом середовища – від звичайної банки води до лез
циркулярної пили та машинами (Рисунок 1.15).

Рисунок 1.15 – Приклад взаємодії з об’єктом


31

За допомогою нової зброї – гравітаційної гармати – вищезгадані об’єкти


використовувались як додаткова можливість завдати шкоди ворогам. Ближче в
кінці гри гармата могла захоплювати органіку, тобто вороги також ставали
зброєю [19].
Для покращення історії крім пророблених рівнів, розробники дали
персонажам гнучку міміку. Аніматори використовували систему доктора Пола
Екмана, який у 1970х роках створив словник гримас із найпростіших описів.
Таким чином за допомогою бібліотеки емоцій та переходу між ними була
можливість уникнути неприродні рухи обличчя персонажів [20].
32

2 ПРОЕКТУВАННЯ ГРИ

2.1 Вибір ігрового рушія

Перший крок в розробці власної гри – це вибір ігрового рушія на якому вона
буде створена. Вибір може залежати від будь-якого фактору, чи це потужність
комп’ютера на якому буде розробка проекту, чи це власні вподобання розробника,
наприклад зручність інтерфейсу програми чи мова програмування. Нижче буде
наведено популярні ігрові рушії з яких можна почати роботу новачку у сфері
створення відеоігор.

2.1.1 Ігрові рушії

Існує безліч ігрових рушіїв. Багато з них недоступні для публічного


використання, багато з них мають загальну публічну ліцензію.

2.1.1.1 Unity

Розробка американської компанії Unity Technologies, яка вийшла у світ в


2005 році, спрямована на «демократизацію» розробки ігор, зробившими їх
створення доступним для більшої кількості розробників . Спочатку Unity був
ексклюзивом для MacOS [21].
Версія Unity 2.0 вийшла в 2007 році з багатьма новими можливостями.
Випуск мав оптимізований рушій місцевості до детального 3D середовища,
динамічні тіні в реальному часі, спрямоване світло та точкове світло, відтворення
відео та багато іншого. Також випуск мав мережевий шар для розробників для
створення багатокористувацьких ігор на основі протоколу User Datagram.
Коли в 2008 році Apple запустила свій App Store, Unity додала підтримку
iPhone, тим самим рушій став відомим серед розробників ігор для IOS.
33

Unity 3.0 був запущений у вересні 2010 року з функціями розширення


графічних функцій рушія для настільних комп'ютерів та відеоігрових консолей.
Окрім підтримки Android, Unity 3 передбачає інтеграцію інструменту Beast
Lightmap Illuminate Labs 'Beast Lightmap, відкладену візуалізацію, вбудований
редактор дерев, власне відображення шрифтів, автоматичне ультрафіолетове
відображення та аудіофільтри.
У листопаді 2012 року Unity Technologies показала Unity 4.0. Ця версія
додала підтримку DirectX 11 та Adobe Flash, нові засоби анімації під назвою
Mecanim та доступ до попереднього перегляду Linux.
За допомогою Unity 5 рушій покращив своє освітлення та звук. За
допомогою WebGL розробники Unity могли додавати свої ігри до сумісних веб-
браузерів, не потребуючи плагінів для гравців. Unity 5.0 запропонував глобальне
освітлення в режимі реального часу, попередній перегляд світлого відображення,
Unity Cloud, нову аудіосистему та фізичний рушій Nvidia PhysX 3.3. П’яте
покоління рушія Unity також представило ефекти Cinematic Image Effects, щоб
зробити ігри Unity менш загальними. Unity 5.6 додав нові ефекти освітлення та
частинок, оновив загальну продуктивність та додав підтримку Nintendo Switch,
Facebook Gameroom, Google Daydream та графічного API Vulkan. Він представив
4K відеоплеєр, здатний запускати 360-градусні відеоролики для віртуальної
реальності. Однак деякі геймери критикували доступність Unity через великий
обсяг швидко виготовлених ігор, опублікованих на платформі розповсюдження
Steam недосвідченими розробниками, так звані «горори на Unity зі Steam
Greenlight» або ж просто «горори на Unity» (Steam Greenlight давно спочив у 2017
році).
У грудні 2016 року Unity Technologies оголосили, що змінять систему
нумерації версій для Unity з ідентифікаторів, заснованих на послідовності, до
року випуску, щоб вирівняти версію з їх більш частою каденцією випуску. За
Unity 5.6 пішов Unity 2017. Інструменти Unity 2017 демонстрували рушій
візуалізації в режимі реального часу, класифікацію кольорів та світобудування,
аналітику операцій та звітність про ефективність. Unity 2017.2 підкреслив плани
34

Unity Technologies за межами відеоігор. Сюди входили нові інструменти, такі як


Timeline, що дозволяло розробникам перетягувати анімацію в ігри, і Cinemachine,
розумна система камер в іграх. Unity 2017.2 також інтегрував інструменти 3DS
MaxS і Maya Autodesk в рушій Unity для спрощеного обміну активами під час
ітерації ігор [21].
Unity 2018 показав розробникам Scriptable Render Pipeline для створення
графіки високого класу. Сюди входили конвеєр рендерингу високої чіткості для
консолей та ПК, а також легкий конвеєр рендерингу для мобільних, віртуальної
реальності, доповненої реальності та змішаної реальності. Unity 2018 також
включав інструменти машинного навчання, такі як Imitation Learning, за
допомогою яких ігри вчяться з реальних звичок гравця, підтримка Magic Leap та
шаблони для нових розробників [21].
У 2019 році було додано нове посилання на мову Wolfram, що дозволяє
отримати доступ до функцій високого рівня мови Wolfram від Unity. Виклик
об’єктів Unity з мови Wolfram також став можливим через бібліотеку UnityLink.
Нині мова програмування лише С#, до версії 2017 була підтримка
UnityScript – вид JavaScript спеціально для Unity.
Відомі ігри на Unity: Kerbal Space Program, Ori and the Will of the Wisps,
Pathologic 2, Beat Saber, Subnautica, Subnautica: Below Zero, Slender: The Arrival,
Darkwood, Cities: Skylines (Рисунок 2.1).
35

Рисунок 2.1 – Приклад гри на рушії Unity (Subnautica: Below Zero)


2.1.1.2 Unreal Engine

Вперше був представлений в шутері від першої особи Unreal у 1998 році
(Рисунок 2.2). Створений засновником Epic Games Тімом Суіні. Дeякі технології
були новинкою для того часу, наприклад використанні динамічного графу сцени –
структури даних, які використовуються у векторних графічних редакторах та
комп’ютерних іграх [22]. Ця технологія дозволяє: частково чи повністю
дзеркальні поверхні, варпінг – можливість при прорисовці заміняти зображення
однієї поверхні проекцією зображення на іншу, паралельну їй поверхню та
скайбокс – проектування на поверхні відтворення з іншої точки. Рушій також став
одним з перших, в яких з’явився ефект гало навколо джерел світла, які плавно
згасали, будучи перекриті краями стін по мірі руху гравця [23].
36

Рисунок 2.2 – Unreal 1998

Друга версія вийшла у 2002 році разом з мультиплеєрним шутером


America's Army, який розробила армія США як засіб набору нових солдатів. Нова
версія рушія мала помітний прогрес в рендерингу, а також нові вдосконалення
набору інструментів. Крім можливості роботи рівні майже в 100 разів детальніше,
ніж у Unreal, рушій інтегрував цілий ряд функцій, в тому числі скелетну систему
анімації, яка була представлена у версії PlayStation 2 Unreal Tournament,
кінематичний інструмент для редагування Matinee, системи частинок та експорт
плагінів для 3D Studio Max та Maya. Крім того, користувальницький інтерфейс
для UnrealEd був переписаний на C ++ за допомогою інструментарію wxWidgets.
Фізичні симуляції, такі як зіткнення регдол гравця та довільна жорстка
динаміка тіла, працювали на фізичному рушії Karma. Ігровий процес на основі
транспортних засобів був успішно реалізований з виходом Unreal Tournament
2004, що дозволило широкомасштабну боротьбу. Хоча Unreal Tournament 2003
мав підтримку фізики транспортних засобів через рушій Karma, як показала
тестова карта з "поспішно сконструйованим транспортним засобом", поки Psyonix
37

не створив модифікацію з базового коду Epic, що гра отримала повністю кодовані


транспортні засоби [23].
Спеціалізована версія UE2 під назвою UE2X була розроблена для Unreal
Championship 2: The Liandri Conflict на оригінальній платформі Xbox, що містить
оптимізації, характерні для цієї консолі. У березні 2011 року Ubisoft Montreal
виявив, що UE2 успішно працює на Nintendo 3DS.
Unreal Engine 3 вийшов у 2006 році. Усі розрахунки освітлення та тіней
проводилися за пікселем, а не за вершиною. Що стосується візуалізації, Unreal
Engine 3 забезпечив підтримку високодинамічного рендерингу гамма-
правильного діапазону. Перші ігри, випущені за допомогою Unreal Engine 3, були
Gears of War для Xbox 360 та RoboBlitz для Windows.
Протягом усього життя UE3 були включені значні оновлення, в тому числі
покращене руйнівне середовище, м'яка динаміку тіл, моделювання великого
натовпу, функціональність iOS, інтеграція Steamworks, рішення глобальної
освітленості в режимі реального часу і стереоскопічний 3D на Xbox 360 через
TriOviz.
На Конференції Розробників Ігор (GDC) 19 березня 2014 року Epic Games
випустили Unreal Engine 4 через нову ліцензійну модель. За щомісячну підписку
на рівні 19 доларів США розробникам було надано доступ до повної версії рушія,
в тому числі вихідний код C ++, який можна було завантажити через GitHub. З
будь-якого випущеного продукту стягувався 5% роялті валового доходу. Першою
грою, випущеною за допомогою Unreal Engine 4, стала Daylight, розроблена за
допомогою раннього доступу до рушія та випущена 29 квітня 2014 року.
4 вересня 2014 року Epic випустив Unreal Engine 4 безкоштовно для шкіл та
університетів, в тому числі особисті копії для студентів, які навчаються в
акредитованих програмах розвитку відеоігор, інформатики, мистецтва,
архітектури, моделювання та візуалізації. 19 лютого 2015 року Epic запустила
Unreal Dev Grants - фонд розвитку на 5 мільйонів доларів, спрямований на
надання грантів для творчих проектів за допомогою Unreal Engine 4.
38

У березні 2015 року Epic випустив Unreal Engine 4 разом із усіма


майбутніми оновленнями безкоштовно для всіх користувачів. В обмін на це Epic
встановив вибірковий графік роялті, вимагаючи 5% доходу за продукцію, яка
складає понад 3000 доларів на квартал.
Щоб підготуватися до випуску свого безкоштовного батл-роялю Fortnite у
вересні 2017 року, Epic довелося ввести ряд модифікацій Unreal Engine, які
допомогли йому обробити велику кількість (до 100) підключень до одного
сервера зберігаючи високу пропускну здатність і покращуючи візуалізацію
великого відкритого в грі світу. Компанія заявила, що включить ці зміни до
майбутніх оновлень Unreal Engine.
З відкриттям магазину Epic Games в грудні 2018 року, Epic не стягуватиме
плату за 5% доходу за ігри, які використовують Unreal Engine та випущені через
магазини Epic Games, поглинаючи цю вартість як частину базового 12% -ного
зниження Epic. для покриття інших витрат.
Нині відомо що Unreal Engine 5 буде доступним для розробників в 2021
році.
За допомогою NANITE можливо використовувати неоптимізовані асети прямо в
грі. Це буде економити художникам від 50 до 70 відсотків часу на створення
контенту. LUMEN – глобальне освітлення, яке прораховується в реальному часі.
Дозволяє освітлювати об’єкт з урахуванням перевідбитого світла [24].
Приклади ігор: Star Wars: Jedi Fallen Order, Deus Ex, Postal 2, Lineage 2,
Killing Floor.

2.1.1.3 CryEngine

Продукт компанії Crytek. Усі ігри на його основі мали вставку “Cry” –
Crysis, Far Cry. Перша версія рушія вийшла у 2002 році. Спочатку розроблений як
демонстрація технологій для Nvidia, і коли компанія побачила свій потенціал,
вона перетворилася на гру. Коли були випущені відеокарти з підтримкою 3.0
піксельних і вершинних шейдерів, Crytek випустила версію рушія 1.2, яка
39

використовувала деякі можливості для кращої графіки. Пізніше компанія


розробила CryEngine версії 1.3, яка додала підтримку освітлення HDR. Рушій
отримав ліцензію NCsoft на їх MMORPG, Aion: The Tower of Eternity (Рисунок
2.3). 30 березня 2006 року Ubisoft придбала всі права інтелектуальної власності на
франшизу Far Cry і безстрокову ліцензію на використання CryEngone версії Far
Cry, відомого як Dunia Engine [25].

Рисунок 2.3 – Unreal 1998

Друга версія рушія використовувалися в Crysis, а оновлена версія - Crysis


Warhead, бічна історія Crysis. Рушій був вперше ліцензований французькою
компанії IMAGTP, яка спеціалізується на архітектурних та містобудівних
комунікаціях. Метою ліцензування рушія було створення програми, яка дозволить
клієнтам точно бачити, як виглядатиме будівля чи інша споруда до того, як
розпочато будь-яке фактичне будівництво. Починаючи з 7 березня 2011 року,
Simpson Studios ліцензував CryEngine 2 на використання у віртуальному світі з
масовою багатокористувацькою системою (MMVW), який проходить на
тераформованому Марсі. 11 травня 2007 року Crytek оголосила, що
40

використовуватиме рушій для створення гри, заснованої на їх новій


"інтелектуальній власності". Також підтверджено, що це не було б частиною
Crysis і насправді може навіть не бути шутером від першої особи. 17 вересня 2007
року коледж мистецтва та дизайну Рінглінг став першим вищим навчальним
закладом у світі, який ліцензував CryEngine 2 для освітніх цілей.
На Конференції розробників ігор 2009, яка проходила з 25 по 27 березня,
Crytek представив CryEngine 3 і продемонстрував це на консолях Xbox 360 та
PlayStation 3. Новий рушій розроблявся для використання в Microsoft Windows,
PlayStation 3, Xbox 360 та Wii U. Що стосується платформи ПК, то рушій
підтримує розробку в DirectX 9, 10 та 11. З 1 червня 2009 року було оголошено,
що Crysis 2 буде розроблений Crytek на їхньому абсолютно новому рушії.
CryEngine 3 вийшов 14 жовтня 2009 року.
21 серпня 2013 року Crytek перейменував CryEngine (починаючи з версії
3.6.0) на просто «CryEngine» і оголосив, що наступний CryEngine не матиме
номеру версії. Причиною такого рішення стало твердження, що цей новий рушій
майже не має подібності з попередніми версіями CryEngine. Однак набори
розробки, доступні ліцензіатам, все ще використовують номери версій. Нова
версія CryEngine додає підтримку Linux та консолей, таких як PlayStation 4, Xbox
One та Wii U. Подальші виступи на заходах також показали використання
CryEngine в системах віртуальної реальності [25].
22 березня 2016 року Crytek оголосив про нову версію CryEngine під назвою
CryEngine V. Крім того, була введена нова модель ліцензування з моделлю
"плати, скільки хочеш" для використання та доступу до вихідного коду.
21 вересня 2017 року було випущено CryEngine 5.4., додавши рендер Vulkan
API у вигляді бета-версії, інтеграцію речовин та інших функцій, включаючи нові
шаблони C #, оновлення системи об’єктів та нові методи згладжування.
20 березня 2018 року Crytek змінив ліцензування з "плати, скільки хочеш",
на 5% модель розподілу доходу [25].
Приклади ігор: Far Cry, Crysis, Warface, Kingdom Come: Deliverence, Prey,
Ryse: Son of Rome (Рисунок 2.4).
41

Рисунок 2.4 – Unreal 1998

2.1.2 Порівняння рушіїв

Порівняння буде доволі простим але зрозумілим для тих, хто бажає почати
роботу з нижченаведеними ігровими рушіями, але не знає чи зможе впоратися з
ними.
2.1.2.1 Мова програмування

Малоймовірно те, що людина обере ігровий рушій без знання мови


програмування, на якому пишуться скрипти.
Unity підтримує C#, хоча раніше була підтримка коду на UnityScript –
схожий на JavaScript синтаксис. Нині від нього відмовилися.
Unreal Engine та CryEngine підтримують лише С++.

2.1.2.2 Доступність матеріалів


42

Не менш важливий фактор при виборі рушія є бібліотека готових асетів та


текстур для розробника. Чим більша бібліотека, тим більше варіантів.
Unity має власну бібліотеку Unity Asset Store, в якій можливо купити або
завантажити безкоштовні моделі, додатки, інструменти, ефекти та навіть аудіо
(Рисунок 2.5).

Рисунок 2.5 – Unity Asset Store


Unreal Engine також має бібліотеку для рушія. На сайті є розділ
“Marketplace”, в якому можна придбати будь-що необхідне для розробки. Для
безкоштовних предметів є навіть власний розділ на сайті, що пришвидшує пошук.
Є навіть предмети, які безкоштовні протягом місяця (Рисунок 2.6).
43

Рисунок 2.6 – Unreal Engine Marketplace

CryEngine як і попередні рушії має власний маркетплейс на сайті. В ньому


можна знайти як і в інших мазанинах категорії 3D та 2D моделі, текстури, демо,
анімації, скрипти, звукові ефекти, плагіни та багато іншого (Рисунок 2.7).
Ще однією приємною новиною можна назвати те, що у вільному доступі є
анімації та моделі з проектів компанії Crytek. Можна завантажити анімації з Crysis
або моделі середовища з Ryse: Son of Rome .
44

Рисунок 2.7 – CryEngine Markeplace

2.1.2.3 Ціна

Unity безкоштовна доки прибуток компанії не перевищує 100000$ США на


рік (Personal). Якщо прибуток до 200000$, то тариф 40 доларів в місяць (Plus), а
від 200000$ прибутку тариф від 150 доларів та більше (Pro та Enterprise) [26].
Unreal Engine безкоштовний доки гра не монетизується, в іншому випадку
ліцензія нараховує 5% роялті, наприклад коли валовий дохід від проекту
перевищує мільйон доларів США [23].
CryEngine має модель 5% з отриманого доходу з проекту [25].

2.1.2.4 Висновки

Кожен з рушіїв має свої плюси та мінуси. Для створення гри в даній роботі
буде використано Unity через його підтримку C# та велику кількість нового
матеріалу для самостійного навчання. Версія рушія буде 2018.3.14f1 Personal.
45

2.2 Ігровий рушій Unity

2.2.1 Загальна інформація

Unity можна завантажити напряму або з Unity Hub, яка допомагає шукати,
завантажувати та управляти проектами та завантаженнями. За допомогою Unity
Hub можна вручну додати версію редактора (Рисунок 2.8).

Рисунок 2.8 – Unity Hub

2.2.2 Знайомство з інтерфейсом

Головне вікно редактора складається з вкладених вікон, які можна


переставляти, групувати, від'єднувати та стикувати. Це означає, що зовнішній
вигляд редактора може відрізнятися від одного проекту до іншого, а від одного
розробника до іншого, залежно від особистих уподобань та того, яким типом
роботи ви займаєтесь [27].
46

Розташування вікон за замовчуванням дає практичний доступ до


найпоширеніших вікон. Найпоширеніші та корисні вікна показані у своїх за
замовчуванням позиціях нижче (Рисунок 2.9).

Рисунок 2.9 – Розташування вікон за замовчуванням

2.2.2.1 Вікно проекту

У вікні проекту відображається бібліотека тих об’єктів, які можна


використовувати у проекті. Коли ви імпортуєте асети у свій проект, вони
відображаються тут [27] (Рисунок 2.10).
47

Рисунок 2.10 – Вікно проекту

2.2.2.2 Перегляд сцени

Перегляд сцени дозволяє візуально переміщатися та редагувати сцену.


Перегляд сцени може показувати 3D або 2D перспективу, залежно від типу
проекту, над яким ви працюєте. Дізнатися більше про вигляд сцени та перегляд
гри можна в документації [27] (Рисунок 2.11).

Рисунок 2.11 – Перегляд сцени


48

2.2.2.3 Вікно ієрархії

Вікно ієрархії - це ієрархічне подання тексту кожного об'єкта на сцені.


Кожен елемент сцени має запис в ієрархії, тому два вікна по своїй суті пов'язані
між собою. Ієрархія розкриває структуру того, як об’єкти прикріплюються один
до одного (Рисунок 2.12).

Рисунок 2.12 – Вікно ієрархії

2.2.2.4 Вікно інспектора

Вікно інспектора дозволяє переглядати та редагувати всі властивості


обраного на даний момент об’єкта. Оскільки різні типи об'єктів мають різні
набори властивостей, компонування та вміст вікна інспектора будуть різними [27]
(Рисунок 2.13).
49

Рисунок 2.13 – Вікно інспектора.

2.2.2.5 Панель інструментів

Панель інструментів забезпечує доступ до найважливіших робочих


функцій. Зліва він містить основні інструменти для маніпулювання сценографією
та об'єктами всередині нього. У центрі - гра, пауза та крок управління. Кнопки
праворуч надають доступ до хмарних служб Unity та свого облікового запису
Unity, далі меню видимості шарів і, нарешті, меню макета редактора (яке містить
декілька альтернативних макетів для вікон редактора та дозволяє зберігати власні
макети) (Рисунок 2.14).
Панель інструментів не є вікном і є єдиною частиною інтерфейсу Unity, яку
не можна змінити [27].

Рисунок 2.14 – Панель інструментів


50

2.3 Вибір додаткових інструментів та необхідних матеріалів

2.3.1 Моделі та текстури

Усі моделі та текстури були завантажені з Unity Asset Store. Моделі зброї та
патронів були завантажені з платформи Scetchfab.

2.3.2 Обробка зображень

Для створення лого, власних асетів прицілювання, мінікарти було


використано Adobe Photoshop CC 2019.

2.3.3 Звукове оформлення

Необхідні звуки ефектів були завантажені з Unity Asset Store, freesound.com,


youtube. Фрази були записані за допомогою Audacity. Фонова музика взята з
відкритої фонотеки Youtube.

2.3.4 Плагіни

Було завантажено плагін для пост-процесингу для корекції кольору сцени та


корекції світла та тіней.

2.3.5 Текстовий редактор

Для створення та редагування скриптів було використано Microsoft Visual


Studio 2019. Виклик програми виконується із самого Unity, що пришвидшує
роботу.
51

2.3.6 Відеоматеріали для навчання

Для створення гри були використані онлайн уроки ютуб каналів Jimmy
Vegas [28] та Brackeys [29]. У разі виникнення помилок під час розробки
доводилося шукати вирішення проблеми на форумах або самостійно вирішувати
проблему.
52

3 РОЗРОБКА ГРИ

3.1 Реалізація класів

Повний вміст класів наведений в Додатку А.

3.1.1 A001Spider.cs

Запускає звукову доріжку із субтитрами після контакту з тригером.

3.1.2 A002Door.cs

Запускає звукову доріжку із субтитрами після контакту з тригером за умови


якщо в гравця нема з собою пістолета.

3.1.3 AmmoPickup.cs

Додає патрони пістолету після контакту з тригер боксом.

3.1.4 AmmoPickupSMG.cs

Додає патрони для пістолета-кулемета після контакту з тригер боксом.

3.1.5 BarrelBang.cs

Знищує бочку при попадання в неї.

3.1.6 BarrelBlow.cs

Запуск звуку вибуху бочки.


53

3.1.7 CaveDoor.cs

Скрипт для двері за допомогою якої можна перейти на наступний рівень.


Має в собі перевірку на наявність у гравця пістолета.

3.1.8 CaveDoorExit.cs

Скрипт для двері за допомогою якої можна завершити гру.

3.1.9 CreackyDoorOpen.cs

Скрипт для відчинення двері у покинутому будинку.

3.1.10 CredToMenu.cs

Повертає від титрів до головного меню.

3.1.11 CrossAnimate.cs

Анімація хреста прицілювання.

3.1.12 CutScene01.cs

Запуск анімованої сцени на початку гри.

3.1.13 EnemyScript.cs

Скрипт здоров’я зомбі. Якщо здоров’я впаде до 0, то буде запущена


анімація смерті та знищення об’єкту.
54

3.1.14 EnemyScriptSpider.cs

Скрипт здоров’я павука. Якщо здоров’я впаде до 0, то буде запущена


анімація смерті та знищення об’єкту.

3.1.15 GameOverToMenu.cs

Скрипт відповідає за тривалість екрану Game Over та перехід у головне


меню.

3.1.16 GlobalAmmo.cs

Показує загальну кількість патронів та завантажених у магазин.

3.1.17 GlobalHealth.cs

Зберігає в собі здоров’я гравця. Якщо здоров’я впаде до 0, то завантажиться


сцена завершення гри.

3.1.18 GlobalScore.cs

Зберігає кількість очок.

3.1.19 GunFire.cs

Механіка стрільби з пістолета. У випадку натискання лівої кнопки миші


запускається звук стрільби, часточки порохового диму, анімація стрільби та
відбирається патрон із загальної кількості.
55

3.1.20 GunFireSMG.cs

Механіка стрільби з пістолета-кулемета. У випадку натискання лівої кнопки


миші запускається звук стрільби, часточки порохового диму, анімація стрільби та
відбирається патрон із загальної кількості. Підтримує стрільбу не по одному
патрону.

3.1.21 HandGunDamage.cs

Механіка попадання в об’єкти. Прописано силу пошкодження від кулі,


вигляд місця пошкодження та ефекти в залежності від типу ворога або від
поверхні.

3.1.22 HandGunReload.cs

За його допомогою можна перезарядити пістолет. Анімація та звук


присутні.

3.1.23 HealthMonitor.cs

Описує поведінку візуального монітору здоров’я гравця. При кожній


мінусації двох очок здоров’я зникає одна плашка здоров’я. Усього цих плашок 5
штук.

3.1.24 MainMenuOptions.cs

Зберігає функції кнопок у головному меню. Можна запустити гру, перейти


до титрів та вийти із гри в систему.
56

3.1.25 OpenDoor001.cs

Відчиняє двері за допомогою взаємодії з кнопкою.


3.1.26 PauseGame.cs

Зупиняє гру при виході в меню. Можна вийти у головне меню,


перезапустити гру, продовжити гру.

3.1.27 PickUp9mm.cs

Тригер для взяття пістолету. Пістолет на рівні зникає і активується в


інвентарі гравця.

3.1.28 PickUpSMG.cs

Тригер для взяття пістолета-кулемета. Зброя на рівні зникає і активується в


інвентарі гравця.

3.1.29 PlayerCasting.cs

Зберігає відстань до об’єкту. Таким чином гравець може взаємодіяти з


об’єктами по типу кнопки для відчинення дверей.

3.1.30 RespawnLevel.cs

Перезавантажує рівень.

3.1.31 SkyRotation.cs

Анімація небесного полотна.


57

3.1.32 SMGReload.cs

Скрипт перезарядки пістолета-кулемета.

3.1.33 SniperScopeActive.cs

Скрипт для прицілювання. При натисканні правої кнопки миші поле зору
зменшується та наскладується зображення прицілу. Коли кнопка відпускається,
тоді поле зору повертається до норми.

3.1.34 SpiderFollow.cs

Скрипт поведінки штучного інтелекту павука. Прописані умови для


пересування, бездіяльності та атаки. Також прописано які звуки будуть при
отриманні поранень гравцем.

3.1.35 SpiderScore.cs

Додає до загальної кількості балів бали за попадання у павука.

3.1.36 SplashToMenu.cs

Анімація переходу до головного меню після лого.

3.1.37 WeaponSwitch.cs
58

Дозволяє змінювати активну зброю прокручуванням колеса та числовими


клавішами на клавіатурі. Для роботи потрібно сховати зброю в об’єкт на який
накладається скрипт.

3.1.38 ZombieFollow.cs

Скрипт поведінки штучного інтелекту зомбі. Прописані умови для


пересування, бездіяльності та атаки. Також прописано які звуки будуть при
отриманні поранень гравцем.

3.1.39 ZombieScore.cs

Додає до загальної кількості балів бали за попадання у зомбі.

3.1.40 ZScore25.cs

Додає до загальної кількості балів бали за попадання у мішень (синя зона).

3.1.41 ZScore50.cs

Додає до загальної кількості балів бали за попадання у мішень (біла зона).

3.1.42 ZScore100.cs

Додає до загальної кількості балів бали за попадання у мішень (червона


зона).

3.2 Реалізація дизайну рівнів

Всього у грі 2 рівні. Нижче наведено загальний вигляд ігрової площини, на


59

якій було розташовано елементи рівнів гри (Рисунок 3.1).

Рисунок 3.1 – Загальний вигляд ігрової площини.

Перший рівень починається у закритій кімнаті із двома ящиками зі зброєю на


них. Після входу в наступну кімнату гравець має можливість підібрати патрони
для зброї та протестувати стрільбу по мішені. У наступному коридорі буде зомбі
та додаткові патрони для зброї. Для виходу на відкриту місцевість треба
натиснути на кнопку для того, щоб відчинити двері (Рисунок 3.2).
60

Рисунок 3.2 – План «будівлі», де починається гра. Стелю вимкнено для


демонстрації.
Коли гравець виходить на місцевість, тоді починає програватися звукова
доріжка та субтитри, бо на виході з будівлі лежить тригер бокс зі скриптом. Далі
доведеться зустріти трьох павуків.
Якщо слідувати за доріжками, то можна потрапити до майже знищеного
будинку. Також є просто покинутий будинок. Якщо зайти у нього, то можна
підібрати патрони до зброї.
Остання доріжка приводить до входу у печеру. Біля дверей знаходиться
тригер бокс. Якщо гравець не підібрав на початку гри пістолет, то запуститься
скрипт тригер боксу із аудіодоріжкою та субтитрами.
Якщо гравець має із собою пістолет, то він має змогу відчинити двері та
пройти на другий рівень.
Щоб гравець не бачив краї ігрового світу, на поверхні були намальовані
пагорби та гори. Щоб поверхня не була пустою, було додано дерева та траву
відповідними пензлями для додавання дерев, трави або квітів (Рисунок 3.3).
61

Рисунок 3.3 – План відкритої місцевості.

Другий рівень представляє з себе невелику печеру з двома дверима та


деяким камінням для кращого дизайну середовища (Рисунок 3.4). Перші двері –
позаду гравця. Це ніби ті самі двері, через які ми пройшли на наступний рівень.
Другі двері – вихід з рівня. Коли гравець взаємодіє з дверима, то екран
затемнюється та переходить у головне меню. Тим самим ми розуміємо що гра
закінчена.
62

Рисунок 3.4 – План відкритої місцевості.

3.3 Реалізація інтерфейсу користувача

3.3.1 Головний інтерфейс

Всю гру користувач бачить головний інтерфейс. Нижче показано його


вигляд (Рисунок 3.6)
63

Рисунок 3.5 – Головний інтерфейс.

Зверху ми бачимо плашку Score, яка відповідає за кількість балів на даний


момент гри.
Зліва можна побачити Objectives – список тих задач, які треба виконати.
Кожна виконана задача позначається червоним значком «виконано». Для того
щоб задачі могли позначатися як виконі, треба прописати у скриптах зміни
вигляду чекбоксів задач з пустих на заповнених «пташкою» (Рисунок 3.6).

Рисунок 3.6 – Приклад усіх виконаних задач.


64

Знизу зліва можна побачити мінікарту. Гравець позначений як чорна стрілка


посередині. Для того щоб карта відповідала дійсності, над гравцем була
поставлена камера, зображення якої і передається на мінікарту. В ієрархії об’єктів
ця камера схована усередині об’єкту гравця, тому вона пересувається разом з
гравцем.
Зверху справа можна побачити візуальне відображення здоров’я гравця.
Усього 10 очок здоров’я або ж 5 червоних плашок. Коли гравець отримає
поранення і загалом втрачає 2 очка здоров’я, тоді плашка зникає (Рисунок 3.7).

Рисунок 3.7 – Приклад відображення здоров’я. В гравця лише 4 очка.

Коли ж здоров’я закінчиться, то закінчиться гра і з’явиться відповідний


екран (Рисунок 3.8).
65

Рисунок 3.8 – Екран завершення гри у випадку втрати усього здоров’я.


Знизу справа можна побачити кількість патронів та назва активної на даний
момент зброї (Рисунок 3.9). Велика цифра – кількість патронів у магазині. Мала
цифра – загальна кількість патронів у гравця.

Рисунок 3.9 – Кількість патронів та вид зброї.

Посередині можна побачити хрест для наведення на ворога (Рисунок 3.10).


Кожний постріл запускає анімацію віддалення хреста від гравця і повернення на
початкову позицію.

Рисунок 3.10 – Хрест для наведення.

3.3.2 Меню паузи

Якщо натиснути на кнопку Esc, то гра поставиться на паузу і з’явиться


меню паузи (Рисунок 3.11.). Воно дуже просте. Є три кнопки. Перша – це Resume.
Якщо на неї натиснути, то гра вийде з паузи і гра продовжиться, а меню зникне.
Друга кнопка – це Respawn. При натисканні на неї гра перезавантажується і
починається перший рівень. Третя кнопка – Quit Game. При натисканні на неї
66

завантажується сцена головного меню.

Рисунок 3.11 – Меню паузи.

3.3.3 Головне меню

Після запуску гри ми бачимо заставку (Рисунок 3.12), після чого


потрапляємо в головне меню (Рисунок 3.13).
67

Рисунок 3.12 – Головне меню.

Рисунок 3.13 – Головне меню.

Кнопка Play запускає гру. Кнопка Load створена для майбутньої можливості
збереження гри з усією статистикою гравця. Кнопка Credits запускає титри до гри
(Рисунок 3.14). Після їх закінчення гравця переносить назад до головного меню.
68

Рисунок 3.14 – Екран титрів.


При натисканні на Quit програма завершиться і користувач повернеться в
операційну систему.

3.4 Висновки

Була створена гра на рушії Unity під Windows. Гра представляє собою
шутер від першого обличчя, де гравцю потрібно знайти вихід на інший рівень. В
якості перешкоди на гравця будуть нападати зомбі та павуки. В якості допомоги
по рівню будуть розкидані патрони для запобігання втрати боєздатності
незалежно від навичок гравця у стрільбі.
69

ВИСНОВКИ

За результатами написання кваліфікаційної роботи «Розробка FPS гри на


ігровому рушії Unity» було отримано наступні висновки:
1. Існує велика кількість жанрів ігор. Кожна гра може містити в собі ознаки
одного або декількох жанрів одночасно;
2. Існує велика кількість ігрових рушіїв, які доступні для роботи всім
бажаючим. Рушії мають власні особливості;
3. Була розроблена безкоштовна десктопна гра для операційної системи
Windows в жанрі FPS;
4. Розроблена гра демонструє можливості та доступність рушія гри Unity.
Під час створення кваліфікаційної роботи було розширено знання та освоєні
навички роботи з ігровим рушієм, в тому числі створення анімації тривимірних
моделей, отримано досвід роботи з мовою програмування C# за допомогою
створення власного коду гри.
Здобуті результати надалі можна покращити шляхом більш поглибленого
вивчення тематичного матеріалу та збільшенню часу застосування засвоєного
матеріалу на практиці шляхом створення нових ігор.
70

ПЕРЕЛІК ВИКОРИСТАНИХ ДЖЕРЕЛ

1. List of video game genres [Електронний ресурс]. – Режим доступу: URL:


https://en.wikipedia.org/wiki/List_of_video_game_genres
2. Бойовик (жанр відеоігор) [Електронний ресурс]. – Режим доступу: URL:
https://uk.wikipedia.org/wiki/%D0%91%D0%BE%D0%B9%D0%BE
%D0%B2%D0%B8%D0%BA_(%D0%B6%D0%B0%D0%BD%D1%80_
%D0%B2%D1%96%D0%B4%D0%B5%D0%BE%D1%96%D0%B3%D0%BE
%D1%80)
3. Adventure game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Adventure_game
4. Action-adventure game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Action-adventure_game
5. Role-playing video game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Role-playing_video_game
6. Simulation video game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Simulation_video_game
7. Strategy video game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Strategy_video_game
8. Sports game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Sports_game
9. Single-player video game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Single-player_video_game
10. Cooperative gameplay [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Cooperative_gameplay
11. Multiplayer video game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Multiplayer_video_game
12. Shooter game [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Shooter_game
71

13. Firest-person shooter [Електронний ресурс]. – Режим доступу: URL:


https://en.wikipedia.org/wiki/First-person_shooter
14. Binary space partitioning [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Binary_space_partitioning
15. Doom WASN’T 3D! – Digressing and Sidequesting [Електронний ресурс].
– Режим доступу: URL: https://www.youtube.com/watch?v=zb6Eo1D6VW8
16. Doom (1993 video game) [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Doom_(1993_video_game)
17. Crysis 10 Years On: Why It’s Still Melting The Most Powerful Gaming PCs
[Електронний ресурс]. – Режим доступу: URL: https://www.youtube.com/watch?
v=PcYA-H3qpTI
18. Screen space ambient occlusion [Електронний ресурс]. – Режим доступу:
URL: https://uk.wikipedia.org/wiki/Screen_space_ambient_occlusion
19. One Series Changed Gaming Forever: Half-Life [Електронний ресурс]. –
Режим доступу: URL: https://www.youtube.com/watch?v=_KNWsb78urY
20. История вселенной Half-Life. Эпизод второй [Електронний ресурс]. –
Режим доступу: URL: https://www.youtube.com/watch?
v=SQD4LP_lOkg&list=PL0fCllKrRQE7F6oSOhlhzqmCbm7LhtMZG&index=2
21. Unity (game engine) [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Unity_(game_engine)
22. Граф сцены [Електронний ресурс]. – Режим доступу: URL:
https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D1%84_
%D1%81%D1%86%D0%B5%D0%BD%D1%8B
23. Unreal Engine [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/Unreal_Engine
24. Как Unreal Engine 5 изменит игры. Разбор трейлера игрового движка на
PS5 [Електронний ресурс]. – Режим доступу: URL:
https://www.youtube.com/watch?v=2Rtxdvd3kGU
25. CryEngine [Електронний ресурс]. – Режим доступу: URL:
https://en.wikipedia.org/wiki/CryEngine
72

26. Choose the plan that is right for you [Електронний ресурс]. – Режим
доступу: URL: https://store.unity.com/compare-plans
27. Learning the interface [Електронний ресурс]. – Режим доступу: URL:
https://docs.unity3d.com/2018.3/Documentation/Manual/LearningtheInterface.html
28. [COMPLETE] How to Make An FPS Unity Tutorials [Електронний ресурс].
– Режим доступу: URL: https://www.youtube.com/playlist?list=PLZ1b66Z1KFKh-
auyvzNkOBFLWf6dH6iEH
29. Brackeys [Електронний ресурс]. – Режим доступу: URL:
https://www.youtube.com/user/Brackeys
73

ДОДАТКИ
74

Найменування

Документація

ЧНТУ «Розробка FPS гри

на ігровому

рушії Unity»

Повний код гри

Комплекси

Операційна система

Microsoft Windows 10

Unity

Microsoft Visual Studio 2019


75

ДОДАТОК А

A001Spider.cs
using System.Collections;
76

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

public class A001Spider : MonoBehaviour


{
public GameObject theSubs;
public AudioSource spiderVoice;

private void OnTriggerEnter(Collider other)


{
StartCoroutine(SpiderSub());
this.GetComponent<BoxCollider>().enabled = false;
}
IEnumerator SpiderSub()
{
spiderVoice.Play();
theSubs.GetComponent<Text>().text = "Spiders? No way.";
yield return new WaitForSeconds(2);
theSubs.GetComponent<Text>().text = "";
}
}

A002Door.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class A002Door : MonoBehaviour


{
public GameObject theSubs;
public AudioSource doorVoice;

private void OnTriggerEnter(Collider other)


{
StartCoroutine(SpiderSub());
this.GetComponent<BoxCollider>().enabled = false;
}
IEnumerator SpiderSub()
{
doorVoice.Play();
theSubs.GetComponent<Text>().text = "I can't go without gun";
yield return new WaitForSeconds(2);
theSubs.GetComponent<Text>().text = "";
yield return new WaitForSeconds(3);
this.GetComponent<BoxCollider>().enabled = true;
}
}

AmmoPickup.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AmmoPickup : MonoBehaviour


{
public AudioSource AmmoSound;
void OnTriggerEnter(Collider other)
{
77

AmmoSound.Play();

if (GlobalAmmo.LoadedAmmo == 0)
{
GlobalAmmo.LoadedAmmo += 10;
this.gameObject.SetActive(false);
}
else
{
GlobalAmmo.CurrentAmmo += 10;
this.gameObject.SetActive(false);
}
}
}

AmmoPickupSMG.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AmmoPickupSMG : MonoBehaviour


{
public AudioSource AmmoSound;
void OnTriggerEnter(Collider other)
{
AmmoSound.Play();

if (GlobalAmmo.LoadedAmmo == 0)
{
GlobalAmmo.LoadedAmmo += 30;
this.gameObject.SetActive(false);
}
else
{
GlobalAmmo.CurrentAmmo += 30;
this.gameObject.SetActive(false);
}
}
}

BarrelBang.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BarrelBang : MonoBehaviour


{
public AudioSource BangSound;

private void OnCollisionEnter(Collision collision)


{
if (collision.relativeVelocity.magnitude > 1)
{
BangSound.Play();
}
}
}
BarrelBlow.cs
using System.Collections;
78

using System.Collections.Generic;
using UnityEngine;

public class BarrelBlow : MonoBehaviour


{
public int EnemyHealth = 5;
public GameObject TheBarrel;
public GameObject FakeBarrel;

void DeductPoints(int DamageAmount)


{
EnemyHealth -= DamageAmount;
}

void Update()
{
if (EnemyHealth <= 0)
{
TheBarrel.SetActive(false);
FakeBarrel.SetActive(true);
}
}

CaveDoor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class CaveDoor : MonoBehaviour


{
public float TheDistance;
public GameObject ActionDisplay;
public AudioSource creakSound;
public GameObject fadeOutScreen;
public int takenGun;

void Update()
{
TheDistance = PlayerPrefs.GetFloat("TheCasting");
takenGun = PlayerPrefs.GetInt("TakeAGun");
}

void OnMouseOver()
{
if (takenGun == 1) {
if (TheDistance <= 3)
{
ActionDisplay.GetComponent<Text>().text = "Enter Cave";
ActionDisplay.SetActive(true);
}
if (Input.GetButtonDown("Action"))
{
if (TheDistance <= 3)
79

{
creakSound.Play();
fadeOutScreen.SetActive(true);
StartCoroutine(EnterTheCave());
GetComponent<BoxCollider>().enabled = false;
ActionDisplay.SetActive(false);
SceneManager.LoadScene(6);
}
}
}
}

void OnMouseExit()
{
ActionDisplay.SetActive(false);
}
IEnumerator EnterTheCave()
{
fadeOutScreen.GetComponent<Animation>().Play("FadeOutAnim");
yield return new WaitForSeconds(1.5f);
SceneManager.LoadScene(6);
}
}

CaveDoorExit.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class CaveDoorExit : MonoBehaviour


{
public float TheDistance;
public GameObject ActionDisplay;
public AudioSource creakSound;

void Update()
{
TheDistance = PlayerPrefs.GetFloat("TheCasting");
}

void OnMouseOver()
{
if (TheDistance <= 3)
{
ActionDisplay.GetComponent<Text>().text = "End Game";
ActionDisplay.SetActive(true);
}
if (Input.GetButtonDown("Action"))
{
if (TheDistance <= 3)
{
creakSound.Play();
StartCoroutine(ExitTheCave());
GetComponent<BoxCollider>().enabled = false;
ActionDisplay.SetActive(false);
SceneManager.LoadScene(1);
}
}
80

void OnMouseExit()
{
ActionDisplay.SetActive(false);
}
IEnumerator ExitTheCave()
{
yield return new WaitForSeconds(1.5f);
SceneManager.LoadScene(1);
}
}

CreackyDoorOpen.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CreackyDoorOpen : MonoBehaviour


{
public float TheDistance;
public GameObject ActionDisplay;
public GameObject TheDoor;
public AudioSource CreakSound;

void Update()
{
TheDistance = PlayerPrefs.GetFloat("TheCasting");
}

void OnMouseOver()
{
if (TheDistance <= 3)
{
ActionDisplay.GetComponent<Text>().text = "Open Door";
ActionDisplay.SetActive(true);
}
if (Input.GetButtonDown("Action"))
{
if (TheDistance <= 3)
{
GetComponent<BoxCollider>().enabled = false;
ActionDisplay.SetActive(false);
TheDoor.GetComponent<Animation>().Play("OpenDoorAnim");
CreakSound.Play();
}
}
}

void OnMouseExit()
{
ActionDisplay.SetActive(false);
}
}

CredToMenu.cs
using System.Collections;
81

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

public class CredToMenu : MonoBehaviour


{

void Start()
{
StartCoroutine(ReturnToMenu());
}

IEnumerator ReturnToMenu()
{
yield return new WaitForSeconds(11);
SceneManager.LoadScene(1);
}

CrossAnimate.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CrossAnimate : MonoBehaviour


{
public GameObject UpCurs;
public GameObject DownCurs;
public GameObject LeftCurs;
public GameObject RightCurs;

void Update()
{
if (GlobalAmmo.LoadedAmmo >= 1) {
if (Input.GetButtonDown("Fire1"))
{
UpCurs.GetComponent<Animator>().enabled = true;
DownCurs.GetComponent<Animator>().enabled = true;
LeftCurs.GetComponent<Animator>().enabled = true;
RightCurs.GetComponent<Animator>().enabled = true;
StartCoroutine(WaitingAnim());
}
}
}
IEnumerator WaitingAnim()
{
yield return new WaitForSeconds(0.1f);
UpCurs.GetComponent<Animator>().enabled = false;
DownCurs.GetComponent<Animator>().enabled = false;
LeftCurs.GetComponent<Animator>().enabled = false;
RightCurs.GetComponent<Animator>().enabled = false;
}
}

CutScene01.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
82

public class CutScene01 : MonoBehaviour


{
public GameObject ThePlayer;
public GameObject Cam1;
public GameObject Cam2;
public GameObject TheUI;

void Start()
{
StartCoroutine(CutSceneBegin());
}

IEnumerator CutSceneBegin()
{
yield return new WaitForSeconds(4.5f);
Cam2.SetActive(true);
Cam1.SetActive(false);
yield return new WaitForSeconds(4.5f);
ThePlayer.SetActive(true);
TheUI.SetActive(true);
Cam2.SetActive(false);
}
}

EnemyScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyScript : MonoBehaviour


{
public int EnemyHealth = 10;
public GameObject TheZombie;

void DeductPoints(int DamageAmount)


{
EnemyHealth -= DamageAmount;
}

void Update()
{
if (EnemyHealth <= 0)
{
this.GetComponent<ZombieFollow>().enabled = false;
TheZombie.GetComponent<Animation>().Play("Dying");
StartCoroutine(EndZombie());
}
}

IEnumerator EndZombie()
{
yield return new WaitForSeconds(1);
Destroy(gameObject);
}
}

EnemyScriptSpider.cs
using System.Collections;
83

using System.Collections.Generic;
using UnityEngine;

public class EnemyScriptSpider : MonoBehaviour


{
public int EnemyHealth = 15;
public GameObject TheSpider;

void DeductPoints(int DamageAmount)


{
EnemyHealth -= DamageAmount;
}

void Update()
{
if (EnemyHealth <= 0)
{
this.GetComponent<SpiderFollow>().enabled = false;
TheSpider.GetComponent<Animation>().Play("die");
}
}

IEnumerator EndZombie()
{
yield return new WaitForSeconds(1);
Destroy(gameObject);
}
}

GameOverToMenu.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameOverToMenu : MonoBehaviour


{

void Start()
{
StartCoroutine(ReturnToMenuGO());
}

IEnumerator ReturnToMenuGO()
{
yield return new WaitForSeconds(3);
SceneManager.LoadScene(1);
}

GlobalAmmo.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GlobalAmmo : MonoBehaviour


{
84

public static int CurrentAmmo;


public int InternalAmmo;
public GameObject AmmoDisplay;

public static int LoadedAmmo;


public int InternalLoaded;
public GameObject LoadedDisplay;

void Update()
{
InternalAmmo = CurrentAmmo;
InternalLoaded = LoadedAmmo;
PlayerPrefs.SetInt("AmmoLevel", CurrentAmmo);
AmmoDisplay.GetComponent<Text>().text = "" + InternalAmmo;
LoadedDisplay.GetComponent<Text>().text = "" + LoadedAmmo;

}
}

GlobalHealth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GlobalHealth : MonoBehaviour


{
public static int PlayerHealth = 10;
public int InternalHealth;
public GameObject HealthDisplay;

private void Update()


{
InternalHealth = PlayerHealth;
HealthDisplay.GetComponent<Text>().text = "Health " + PlayerHealth;
if (PlayerHealth == 0)
{
SceneManager.LoadScene(3);
}
}

GlobalScore.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GlobalScore : MonoBehaviour


{
public static int CurrentScore;
public int InternalScore;

public GameObject ScoreText;

void Update()
{
85

InternalScore = CurrentScore;
ScoreText.GetComponent<Text>().text = "" + InternalScore;
}
}

GunFire.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GunFire : MonoBehaviour


{
public GameObject Flash;

void Update()
{
if (GlobalAmmo.LoadedAmmo >= 1) {
if (Input.GetButtonDown("Fire1"))
{
AudioSource gunsound = GetComponent<AudioSource>();
gunsound.Play();
Flash.SetActive(true);
StartCoroutine(MuzzleOff());
GetComponent<Animation>().Play("GunShot");
GlobalAmmo.LoadedAmmo -= 1;
}
}
}

IEnumerator MuzzleOff()
{
yield return new WaitForSeconds(0.1f);
Flash.SetActive(false);
}
}

GunFireSMG.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GunFireSMG : MonoBehaviour


{
public GameObject TheSMG;
public AudioSource SMGSound;
public GameObject MuzzleFlash;
public int AmmoCount;
public int Firing;

public GameObject UpCurs;


public GameObject DownCurs;
public GameObject LeftCurs;
public GameObject RightCurs;

void Update()
{
AmmoCount = GlobalAmmo.LoadedAmmo;
if (Input.GetButton("Fire1"))
86

{
if (AmmoCount >= 1)
{
if (Firing == 0)
{
StartCoroutine(SMGFire());
}
}
}
}

IEnumerator SMGFire()
{
Firing = 1;
UpCurs.GetComponent<Animator>().enabled = true;
DownCurs.GetComponent<Animator>().enabled = true;
LeftCurs.GetComponent<Animator>().enabled = true;
RightCurs.GetComponent<Animator>().enabled = true;
GlobalAmmo.LoadedAmmo -= 1;
SMGSound.Play();
MuzzleFlash.SetActive(true);
TheSMG.GetComponent<Animator>().enabled = true;
yield return new WaitForSeconds(0.1f);
MuzzleFlash.SetActive(false);
TheSMG.GetComponent<Animator>().enabled = false;
UpCurs.GetComponent<Animator>().enabled = false;
DownCurs.GetComponent<Animator>().enabled = false;
LeftCurs.GetComponent<Animator>().enabled = false;
RightCurs.GetComponent<Animator>().enabled = false;
Firing = 0;
}
}

HandGunDamage.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HandGunDamage : MonoBehaviour


{
public int DamageAmount;
public float TargetDistance;
public float AllowedRange = 15.0f;

public RaycastHit hit;


public GameObject TheBullet;
public GameObject TheBlood;
public GameObject TheBloodGreen;

void Start()
{
DamageAmount = 5;
}

void Update()
{
if (GlobalAmmo.LoadedAmmo >= 1)
{
if (Input.GetButtonDown("Fire1"))
87

{
RaycastHit Shot;
if (Physics.Raycast(transform.position,
transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{

if (Physics.Raycast (transform.position,
transform.TransformDirection(Vector3.forward), out hit))
{

if (hit.transform.tag == "Zombie")
{
Instantiate(TheBlood, hit.point,
Quaternion.FromToRotation(Vector3.up, hit.normal));
}
if (hit.collider.CompareTag("ZombieHead"))
{
DamageAmount = 10;
Instantiate(TheBlood, hit.point,
Quaternion.FromToRotation(Vector3.up, hit.normal));
}
if (hit.transform.tag == "Spider")
{
Instantiate(TheBloodGreen, hit.point,
Quaternion.FromToRotation(Vector3.up, hit.normal));
}
if (hit.transform.tag == "Untagget")
{
Instantiate(TheBullet, hit.point,
Quaternion.FromToRotation(Vector3.up, hit.normal));
}
}
Shot.transform.SendMessage("DeductPoints", DamageAmount,
SendMessageOptions.DontRequireReceiver);
DamageAmount = 5;
}
}
}
}
}

HandGunReload.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HandGunReload : MonoBehaviour


{
public AudioSource ReloadSound;
public GameObject CrossObject;
public GameObject MechanicsObject;
public int ClipCount;
public int ReserveCount;
public int ReloadAvailable;
88

public GunFire GunComponent;

void Start()
{
GunComponent = GetComponent<GunFire>();
}

void Update()
{
ClipCount = GlobalAmmo.LoadedAmmo;
ReserveCount = GlobalAmmo.CurrentAmmo;

if (ReserveCount == 0)
{
ReloadAvailable = 0;
}
else
{
ReloadAvailable = 10 - ClipCount;
}

if (Input.GetButtonDown("Reload"))
{
if (ReloadAvailable >= 1)
{
if (ReserveCount <= ReloadAvailable)
{
GlobalAmmo.LoadedAmmo += ReserveCount;
GlobalAmmo.CurrentAmmo -= ReserveCount;
ActionReload();
}
else
{
GlobalAmmo.LoadedAmmo += ReloadAvailable;
GlobalAmmo.CurrentAmmo -= ReloadAvailable;
ActionReload();
}
}
StartCoroutine(EnableScripts());

}
}

private IEnumerator EnableScripts()


{
yield return new WaitForSeconds(1.1f);
GunComponent.enabled = true;
CrossObject.SetActive(true);
MechanicsObject.SetActive(true);
}

private void ActionReload()


{
GunComponent.enabled = false;
CrossObject.SetActive(false);
MechanicsObject.SetActive(false);
ReloadSound.Play();
GetComponent<Animation>().Play("HandgunReload");
}
}
89

HealthMonitor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HealthMonitor : MonoBehaviour


{
public GameObject Health04;
public GameObject Health03;
public GameObject Health02;
public GameObject Health01;
public GameObject Health00;
public int CurrentHealth;

void Update()
{
CurrentHealth = GlobalHealth.PlayerHealth;

if (CurrentHealth == 8)
{
if (Health04.transform.localScale.y < 0.0f)
{
Health04.SetActive(false);
}
else
{
Health04.transform.localScale -= new Vector3(0.0f, 0.05f, 0.0f);
}
}

if (CurrentHealth == 6)
{
if (Health03.transform.localScale.y < 0.0f)
{
Health03.SetActive(false);
}
else
{
Health03.transform.localScale -= new Vector3(0.0f, 0.05f, 0.0f);
}
}

if (CurrentHealth == 4)
{
if (Health02.transform.localScale.y < 0.0f)
{
Health02.SetActive(false);
}
else
{
Health02.transform.localScale -= new Vector3(0.0f, 0.05f, 0.0f);
}
}

if (CurrentHealth == 2)
{
if (Health01.transform.localScale.y < 0.0f)
{
Health01.SetActive(false);
}
90

else
{
Health01.transform.localScale -= new Vector3(0.0f, 0.05f, 0.0f);
}
}

if (CurrentHealth == 0)
{
if (Health00.transform.localScale.y < 0.0f)
{
Health00.SetActive(false);
}
else
{
Health00.transform.localScale -= new Vector3(0.0f, 0.05f, 0.0f);
}
}
}
}

MainMenuOptions.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MainMenuOptions : MonoBehaviour


{
public void PlayGame()
{
SceneManager.LoadScene(4);
}

public void CreditScene()


{
SceneManager.LoadScene(2);
}

public void QuitToSystem()


{
Application.Quit();
}
}

OpenDoor001.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class OpenDoor001 : MonoBehaviour


{
public GameObject TextDisplay;
public float TheDistance = PlayerCasting.DistanceFromTarget;

public GameObject TheDoor;


private bool DoorOpen = false;

public GameObject ObjectiveComplete;


91

void Update()
{
TheDistance = PlayerCasting.DistanceFromTarget;
}
void OnMouseOver()
{
if (TheDistance <= 2)
{
TextDisplay.GetComponent<Text>().text = "Press to open!";
}
if (Input.GetButtonDown("Action") && DoorOpen == false)
{
if (TheDistance <= 2)
{
DoorOpen = true;
ObjectiveComplete.SetActive(true);
StartCoroutine("OpenTheDoor");

}
}
}

void OnMouseExit()
{
TextDisplay.GetComponent<Text>().text = "";
}

IEnumerator OpenTheDoor()
{
TheDoor.GetComponent<Animator>().enabled = true;
yield return new WaitForSeconds(1);
TheDoor.GetComponent<Animator>().enabled = false;
yield return new WaitForSeconds(5);
TheDoor.GetComponent<Animator>().enabled = true;
yield return new WaitForSeconds(1);
TheDoor.GetComponent<Animator>().enabled = false;
DoorOpen = false;
}
}

PauseGame.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;
using UnityEngine.SceneManagement;
public class PauseGame : MonoBehaviour
{
public bool Paused = false;
public GameObject ThePlayer;
public GameObject PauseMenu;

void Update()
{
if (Input.GetButtonDown("Cancel"))
{
if (Paused == false)
{
92

Time.timeScale = 0;
Paused = true;
PauseMenu.SetActive(true);
ThePlayer.GetComponent<FirstPersonController>().enabled = false;
Cursor.visible = true;
}
else
{
ThePlayer.GetComponent<FirstPersonController>().enabled = true;
Paused = false;
PauseMenu.SetActive(false);
Time.timeScale = 1;
}
}
}

public void UnpauseGame()


{
ThePlayer.GetComponent<FirstPersonController>().enabled = true;
Paused = false;
PauseMenu.SetActive(false);
Time.timeScale = 1;
}

public void RespawnGame()


{
ThePlayer.GetComponent<FirstPersonController>().enabled = true;
Paused = false;
PauseMenu.SetActive(false);
Time.timeScale = 1;
SceneManager.LoadScene(5);
}
public void QuitGame()
{
ThePlayer.GetComponent<FirstPersonController>().enabled = true;
Paused = false;
PauseMenu.SetActive(false);
Time.timeScale = 1;
SceneManager.LoadScene(1);
}
}

PickUp9mm.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PickUp9mm : MonoBehaviour


{
public float TheDistance = PlayerCasting.DistanceFromTarget;
public GameObject TextDisplay;

public GameObject FakeGun;


public GameObject RealGun;
public GameObject AmmoDisplay;
public AudioSource PickUpAudio;

public GameObject ObjectiveComplete;


93

public GameObject DoorStopper;

public GameObject WeaponHolder;


public GameObject AnotherWeapon2;

void Update()
{
TheDistance = PlayerCasting.DistanceFromTarget;

void OnMouseOver()
{
if (TheDistance <= 2)
{
TextDisplay.GetComponent<Text>().text = "Take 9mm Pistol";
}
if (Input.GetButtonDown("Action"))
{
if (TheDistance <= 2)
{
StartCoroutine(TakeNineMil());
ObjectiveComplete.SetActive(true);
}
}
}

void OnMouseExit()
{
TextDisplay.GetComponent<Text>().text = "";
}

IEnumerator TakeNineMil()
{
PlayerPrefs.SetInt("TakeAGun", 1);
DoorStopper.SetActive(false);
PickUpAudio.Play();
transform.position = new Vector3(0, -1000, 0);
FakeGun.SetActive(false);
RealGun.SetActive(true);
AmmoDisplay.SetActive(true);
WeaponHolder.SetActive(true);
AnotherWeapon2.SetActive(false);
yield return new WaitForSeconds(0.1f);
}
}

PickUpSMG.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PickUpSMG : MonoBehaviour


{
public float TheDistance = PlayerCasting.DistanceFromTarget;
public GameObject TextDisplay;

public GameObject FakeGun;


public GameObject RealGun;
94

public GameObject AmmoDisplay;


public AudioSource PickUpAudio;

public GameObject ObjectiveComplete;

public GameObject Mechanics;

public GameObject WeaponHolder;


public GameObject AnotherWeapon1;

void Update()
{
TheDistance = PlayerCasting.DistanceFromTarget;

void OnMouseOver()
{
if (TheDistance <= 2)
{
TextDisplay.GetComponent<Text>().text = "Take SMG";
}
if (Input.GetButtonDown("Action"))
{
if (TheDistance <= 2)
{
StartCoroutine(TakeNineMil());
Mechanics.SetActive(true);
ObjectiveComplete.SetActive(true);
}
}
}

void OnMouseExit()
{
TextDisplay.GetComponent<Text>().text = "";
}

IEnumerator TakeNineMil()
{
PickUpAudio.Play();
transform.position = new Vector3(0, -1000, 0);
FakeGun.SetActive(false);
RealGun.SetActive(true);
AmmoDisplay.SetActive(true);
WeaponHolder.SetActive(true);
AnotherWeapon1.SetActive(false);
yield return new WaitForSeconds(0.1f);
}
}

PlayerCasting.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCasting : MonoBehaviour


{
public static float DistanceFromTarget;
public float ToTarget;
95

void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position,
transform.TransformDirection(Vector3.forward), out hit))
{
ToTarget = hit.distance;
DistanceFromTarget = ToTarget;
PlayerPrefs.SetFloat("TheCasting", DistanceFromTarget);
}
}
}

RespawnLevel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class RespawnLevel : MonoBehaviour


{

void Start()
{
SceneManager.LoadScene(4);
}

SkyRotation.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkyRotation : MonoBehaviour


{
public float RotateSpeed = 0.5f;

void Update()
{
RenderSettings.skybox.SetFloat("_Rotation", Time.time * RotateSpeed);
}
}

SMGReload.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SMGReload : MonoBehaviour


{
96

public AudioSource ReloadSound;


public GameObject CrossObject;
public GameObject MechanicsObject;
public int ClipCount;
public int ReserveCount;
public int ReloadAvailable;
public GunFireSMG GunComponent;
public GameObject SelectedWapon;
void Start()
{
GunComponent = GetComponent<GunFireSMG>();
}

void Update()
{
ClipCount = GlobalAmmo.LoadedAmmo;
ReserveCount = GlobalAmmo.CurrentAmmo;

if (ReserveCount == 0)
{
ReloadAvailable = 0;
}
else
{
ReloadAvailable = 15 - ClipCount;
}

if (Input.GetButtonDown("Reload"))
{
if (ReloadAvailable >= 1)
{
if (ReserveCount <= ReloadAvailable)
{
GlobalAmmo.LoadedAmmo += ReserveCount;
GlobalAmmo.CurrentAmmo -= ReserveCount;
ActionReloadSMG();
}
else
{
GlobalAmmo.LoadedAmmo += ReloadAvailable;
GlobalAmmo.CurrentAmmo -= ReloadAvailable;
ActionReloadSMG();
}
}
StartCoroutine(EnableScripts());

}
}

private IEnumerator EnableScripts()


{
yield return new WaitForSeconds(1.1f);
GunComponent.enabled = true;
CrossObject.SetActive(true);
MechanicsObject.SetActive(true);
}

private void ActionReloadSMG()


{
GunComponent.enabled = false;
CrossObject.SetActive(false);
97

MechanicsObject.SetActive(false);
ReloadSound.Play();
GetComponent<Animation>().Play("SMGReload");
}
}

SniperScopeActive.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SniperScopeActive : MonoBehaviour


{
public GameObject playerCam;
public GameObject sniperScopeTex;
public GameObject originalCursor;
public int fieldView = 60;
public bool zoomingIn = false;

void Update()
{
if (Input.GetMouseButtonDown(1))
{
if (zoomingIn == false)
{
sniperScopeTex.SetActive(true);
originalCursor.SetActive(false);
StartCoroutine(ZoomingCam());
zoomingIn = true;
}
}
if (Input.GetMouseButtonUp(1))
{
StopAllCoroutines();
fieldView = 60;
playerCam.GetComponent<Camera>().fieldOfView = fieldView;
sniperScopeTex.SetActive(false);
originalCursor.SetActive(true);
zoomingIn = false;
}
}

IEnumerator ZoomingCam()
{
while (fieldView > 25)
{
playerCam.GetComponent<Camera>().fieldOfView = fieldView;
fieldView -= 2;
yield return new WaitForSeconds(0.01f);
}
}

SpiderFollow.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
98

public class SpiderFollow : MonoBehaviour


{
public GameObject ThePlayer;
public float TargetDistance;
public float AllowedRange = 5;
public GameObject TheEnemy;
public float EnemySpeed;
public int AttackTrigger;
public RaycastHit Shot;

public int IsAttacking;


public GameObject ScreenFlash;
public AudioSource Hurt01;
public AudioSource Hurt02;
public AudioSource Hurt03;
public int PainSound;
//public GameObject Wall;

private void Update()


{
transform.LookAt(ThePlayer.transform);
if (Physics.Raycast (transform.position,
transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
EnemySpeed = 0.03f;
if (AttackTrigger == 0)
{
TheEnemy.GetComponent<Animation>().Play("walk");
transform.position = Vector3.MoveTowards (transform.position,
ThePlayer.transform.position, Time.deltaTime);
}
}
else
{
EnemySpeed = 0;
TheEnemy.GetComponent<Animation>().Play("idle");
}
}

if (AttackTrigger == 1)
{
if (IsAttacking == 0)
{
StartCoroutine(EnemyDamage());
}
EnemySpeed = 0;
TheEnemy.GetComponent<Animation>().Play("attack");
}
}

private void OnTriggerEnter(Collider other)


{

AttackTrigger = 1;

}
99

private void OnTriggerExit(Collider other)


{
AttackTrigger = 0;
}

IEnumerator EnemyDamage()
{
IsAttacking = 1;
PainSound = Random.Range(1, 4);
yield return new WaitForSeconds (0.4f);
ScreenFlash.SetActive(true);
GlobalHealth.PlayerHealth -= 2;
if (PainSound == 1)
{
Hurt01.Play();
}
if (PainSound == 2)
{
Hurt02.Play();
}
if (PainSound == 3)
{
Hurt03.Play();
}
yield return new WaitForSeconds(0.09f);
ScreenFlash.SetActive (false);
yield return new WaitForSeconds(1);
IsAttacking = 0;
}
}

SpiderScore.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpiderScore : MonoBehaviour


{
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 50;
}
}

SplashToMenu.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SplashToMenu : MonoBehaviour


{

void Start()
{
StartCoroutine(SplashFinish());
}

IEnumerator SplashFinish()
100

{
yield return new WaitForSeconds(5.5f);
SceneManager.LoadScene(1);
}
}

WeaponSwitch.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WeaponSwitch : MonoBehaviour


{
public int selectedWeapon = 0;
void Start()
{
SelectWeapon();
}

void Update()
{
int previousSelectedWeapon = selectedWeapon;

if (Input.GetAxis("Mouse ScrollWheel") > 0f)


{
if (selectedWeapon >= transform.childCount - 1)
selectedWeapon = 0;
else
selectedWeapon++;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0f)
{
if (selectedWeapon <= 0)
selectedWeapon = transform.childCount - 1;
else
selectedWeapon--;
}

if (Input.GetKeyDown(KeyCode.Alpha1))
{
selectedWeapon = 0;
}

if (Input.GetKeyDown(KeyCode.Alpha2) && transform.childCount >= 2)


{
selectedWeapon = 1;
}

if (previousSelectedWeapon != selectedWeapon)
{
SelectWeapon();
}
}

void SelectWeapon()
{
int i = 0;
foreach (Transform weapon in transform)
{
101

if (i == selectedWeapon)
weapon.gameObject.SetActive(true);
else
weapon.gameObject.SetActive(false);
i++;
}
}
}

ZombieFollow.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZombieFollow : MonoBehaviour


{
public GameObject ThePlayer;
public float TargetDistance;
public float AllowedRange = 5;
public GameObject TheEnemy;
public float EnemySpeed;
public int AttackTrigger;
public RaycastHit Shot;

public int IsAttacking;


public GameObject ScreenFlash;
public AudioSource Hurt01;
public AudioSource Hurt02;
public AudioSource Hurt03;
public int PainSound;

private void Update()


{
transform.LookAt(ThePlayer.transform);
if (Physics.Raycast (transform.position,
transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
EnemySpeed = 0.01f;
if (AttackTrigger == 0)
{
TheEnemy.GetComponent<Animation>().Play("Walking");
transform.position = Vector3.MoveTowards (transform.position,
ThePlayer.transform.position, Time.deltaTime);
}
}
else
{
EnemySpeed = 0;
TheEnemy.GetComponent<Animation>().Play("Idle");
}
}

if (AttackTrigger == 1)
{
if (IsAttacking == 0)
{
StartCoroutine(EnemyDamage());
102

}
EnemySpeed = 0;
TheEnemy.GetComponent<Animation>().Play("Attacking");
}
}

private void OnTriggerEnter(Collider other)


{

AttackTrigger = 1;

private void OnTriggerExit(Collider other)


{
AttackTrigger = 0;
}

IEnumerator EnemyDamage()
{
IsAttacking = 1;
PainSound = Random.Range(1, 4);
yield return new WaitForSeconds (0.4f);
ScreenFlash.SetActive(true);
GlobalHealth.PlayerHealth -= 2;
if (PainSound == 1)
{
Hurt01.Play();
}
if (PainSound == 2)
{
Hurt02.Play();
}
if (PainSound == 3)
{
Hurt03.Play();
}
yield return new WaitForSeconds(0.09f);
ScreenFlash.SetActive (false);
yield return new WaitForSeconds(1);
IsAttacking = 0;
}
}

ZombieScore.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZombieScore : MonoBehaviour


{

void DeductPoints(int DamageAmount)


{
GlobalScore.CurrentScore += 50;
}
}

ZScore25.cs
103

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

public class ZScore25 : MonoBehaviour


{
public GameObject ObjectiveComplete;
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 25;
ObjectiveComplete.SetActive(true);
}
}

ZScore50.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZScore50 : MonoBehaviour


{
public GameObject ObjectiveComplete;
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 50;
ObjectiveComplete.SetActive(true);
}
}

ZScore100.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZScore100 : MonoBehaviour


{
public GameObject ObjectiveComplete;
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 100;
ObjectiveComplete.SetActive(true);
}
}

You might also like