Как создать игру, ничего не умея. Часть вторая: сцена (уровень), квесты, интерактивные объекты

Пост опубликован в блогах iXBT.com, его автор не имеет отношения к редакции iXBT.com
| Обзор | Игры
Предисловие

Привет^ народец, сегодня я продолжу свою попытку создать игру^ используя только информацию из интернета.
Первая часть вот тут — ТЫК.

В этой статье я попробую создать игровую комнату, она же сцена, уровень, локация и так далее, а так же попробуем прописать НПЦ (внутриигровых персонажей) с квестами, и взаимодействие с предметами. Ну что, начнём словоблудие!

Сцена

Для начала откроем наш проект над которым мы работали в прошлой статье, и переименуем нашего персонажа в Player.

Далее^ используя наши познания из прошлого урока^ создаём папку Prefabs, для тех^ кто забыл как это делается, нажимаем на Assets в древе, далее правой кнопкой в папке assets, Create -> Folder.

Далее перетягиваем нашего персонажа Player в папочку Prefabs, что даёт нам возможность его сохранить со всеми настройками и скриптами^ которые мы использовали в прошлой статье. Если выползет диалоговое окно, выбираем Original Prefab, а после в папочке Scene аналогичным способом создаем новую сцену под именем Scene_01 (и снова для самых-самых, правой кнопкой тык, и выбираем Create -> Scene). Это и будет наша рабочая сцена на эту статью, дважды тык на Scene_01 и у нас снова пустая рабочая область.

Смотрим в экран и вот тут начинается главная головная боль, необходимо придумать, как будет выглядеть наш первый уровень, который необходимо построить, а главное продумать его так, чтобы он полностью удовлетворял наши потребности. Обычно для таких целей я беру пачку листов А4 и карандаш, а после несколько дней рисую разные варианты уровня, если что-то мне не нравится после рисовки, я всё равно это оставляю на будущее, поскольку в итоге из всех рисунков и собирается один более-менее играбельный уровень для игры. Но мы сейчас всё делаем по велению интернета, поэтому возьмём за идею стандартную ситуацию.

  • Построим закрытые ворота, перед которыми будут стоять стражники, а за воротами будет город, в который нам необходимо попасть.
  • Стражники нас не пропустят, пока мы не выполним квест.
  • Ворота откроются после выполнения квеста.

Вот такой вот незамысловатый сюжет будет в нашей сцене =)

Строительство

Для начала нам нужна земля, заходим в GameObjects -> 3D Object -> Terrain, это создало нам землю, но она довольно большая для моей сцены, поэтому заходим в Inspector, нажимаем на шестеренку (Terrain Setting) и ищем Mesh Resolution (On Terrain Data) для меня подошли показатели:

  • Terrain Width: 70
  • Terrain Length: 70
  • Terrain Height: 120

Тут я наверное немного поясню ситуацию. Данный Terrain я использовать не буду, у меня есть все готовые префабы для создания играбельной сцены, но для людей, которые собираются САМИ создать свою землю и объекты, прийдётся использовать данную функцию. В ней есть всё необходимое, чтобы сделать из этого квадрата равнины, горы, леса, пустыню. Необходимо просто использовать нужную Вам кисть, и натянуть текстуру. Я же в буду использовать префабы, которые шли в комплекте с персонажем, а Terrain послужит мне границами уровня. (Для тех кто всё же хочет, чтобы я создал игровую область без префабов, пишите в комментариях, тогда будет понятно, нужна ли такая информация).

Используя префабы, я начинаю строительство, выбираю для начала зелень и растягиваю её почти на весь Terrain, далее выбираю ворота, стены, горы, деревья, дорогу, и просто перетаскиваю их в сцену, немного позиционирую, а далее делаю копи-паст и собираю простейший уровень, получилось примерно так.

Все префабы ландшафта я поместил в Terrain, чтобы они не загромождали древо сцены. За 5 минут получилось невесть, что, но если провести за этим делом пару дней, то можно собрать что-то подобное.

Давайте посмотрим как поведёт наш персонаж себя в новом месте проживания. Заходим в папку Prefabs и переносим наш префаб Player в сцену, у меня он появился где-то сбоку, но я простым движением переместил его в начало каменной дороги. После удаляю из сцены Main Camera, потому как к нашему персонажу уже прикреплена камера, и дабы не было конфликтов избавляемся от камеры в сцене. Жму кнопку Play и осматриваю новые земли. Персонаж отлично себя чувствует в новом месте. Исходя из этого мы можем перейти наконец к НПЦ и квестам.

  NPC или неигровые персонажи

В качестве НПЦ мы будем использовать такие же префабы рыцарей, что и наш персонаж. Давайте поставим их перед воротами.

И вот двое из ларца одинаковых с лица стоят и охраняют наши ворота. Им я сразу дал имена NPC_01 и NPC_02, давайте подойдём и посмотрим как это выглядит в игре. 

Да уж, в игре это выглядит так же ужасно, как и в сцене =) Оживим наших горе-охранников, чтобы они не стояли как пугало в поле. Для этого вернёмся к нашей первой статье, где мы оживляли нашего персонажа, и проделываем туже процедуру с болванчиками у ворот. Для тех, кто не помнит, направляемся в mixamo, находим подходящие нам анимации, добавляем их в проект, создаём аниматор контроллер и прикрепляем его к болванчикам.

Я прикрепил анимацию засыпающего человека к одному болванчику, и строго стоящего второму, это мне нужно для более полного погружения для квеста. Я понимаю, что это совсем необязательно, ведь мы не пытаемся создать ААА проект прямо на коленке как Юбисофт (это лично моё мнение), но всё же и создавать Г* мне не хочется, хоть это и попытка сделать всё при помощи интернета. Наконец пришло время для квеста!

Квест

Тут мне пришлось немного использовать крота, дабы прорыть интернет для правильного скрипта и построения квеста. Его выполнение, тоже должно было работать правильно и не вызывать ошибок, и я снова на коне! Давайте приступим.

Для начала создадим папку с названием Quest, а в ней соответственно создадим три скрипта с названиями: Sword, Quest, NPC (названия произвольны, Вы можете их назвать как Вам будет удобнее, но не забывайте тогда исправить class и обращения к скриптам). Первым же будет скрипт Quest:

Скрипт Quest

using UnityEngine;
using System.Collections;
public class Quest: MonoBehaviour
{
public bool quest; // отображает название квеста на экране;
public string MissionText; // название квеста;
public string ObjectTag; // тэг объекта;
public bool MissionObjects; //отображает собран предмет или нет;
public int Money; // количество денег;

void OnGUI()
{

if (quest)
{
GUI.Label(new Rect(20, 80, 300, 30), " " + MissionText); // значение названия квеста будет браться из скрипта NPC;
if (MissionObjects)
{ // если предмет собран;
GUI.Label(new Rect(150, 80, 200, 30), "[Выполнено]"); // выводит надпись;
}
}
}
}

 Его мы добавляем к нашему персонажу, и изменяем его ТЕГ на Player, тег Вы можете поставить в inspector нашего Player 

Далее создаём скрипт NPC

Скрипт NPC

using UnityEngine;
using System.Collections;

public class NPC: MonoBehaviour

{

public bool quest; //переменная, которая обозначает взят квест или нет;
public bool vis; // переменная, которая будет отображать диалог между персонажами;
public string missionText; // Текст который будет отображать наименование квеста;
public string missionTag; //Тэг объекта, который необходимо принести;
private Quest MP; // подключаем скрипт Quest;

void Start()

{
MP = GameObject.FindGameObjectWithTag(«Player»).GetComponent<Quest>(); // определяем что скрипт Quest будет находится на персонаже с тэгом player;
}

void Update()

{
GameObject MissionTagScanner = GameObject.FindGameObjectWithTag(«Player»); // персонаж у которого берем квест будет взаимодействовать только с тем объектом у которого тэг Player;
if (Input.GetKeyDown(KeyCode.E) & Vector3.Distance(transform.position, MissionTagScanner.transform.position) < 2) // При нажатии на клавишу Е и при дистанции между персонажами меньше чем 2;
{
vis = true; // переменная vis принимает значение true;
}
}
void OnGUI()
{
if (vis) // если переменная равна true;
{
if (!quest) // и если квест еще не взят;
{
GUI.Box(new Rect((Screen.width — 300) / 2, (Screen.height — 300) / 2, 300, 300), «Квест»); // то на экране отображается окно с названием Квест;
GUI.Label(new Rect((Screen.width — 300) / 2 + 5, (Screen.height — 300) / 2 + 15, 290, 250), «Куда ломишься, не видишь закрыто, вали отсюда пока не получил по щам.Еще и этот бездельник меч свой потерял вчера, всю ночь искал так и не нашел, теперь вот спит на посту.Сделаем так, принесешь мне потерянный меч моего напарника и я тебя пропущу, берешься? „); // и текстом который описывает квест;
if (GUI.Button(new Rect((Screen.width — 100) / 2, (Screen.height — 300) / 2 + 250, 100, 40), “Ок»)) // при нажатии на кнопку Ok;
{
quest = true; // квест взят;
MP.quest = true; // отображает название квеста на экране;
MP.MissionText = «Принести меч»; // текст квеста;
MP.ObjectTag = missionTag; // тэг объекта который необходимо принести;
vis = false; // все диалоговые окна закрываются;
}
}
else
{ // если же квест уже взят;
GUI.Box(new Rect((Screen.width — 300) / 2, (Screen.height — 300) / 2, 300, 300), «Квест»);
GUI.Label(new Rect((Screen.width — 300) / 2 + 5, (Screen.height — 300) / 2 + 15, 290, 250), «Принес?»); //то описание квеста меняется на другой текст;
if (MP.MissionObjects) // если вы уже подобрали объект;
{
if (GUI.Button(new Rect((Screen.width — 100) / 2, (Screen.height — 300) / 2 + 250, 100, 40), «Да»)) // то появится кнопка да, при нажатии на которую;
{
quest = false; // переменная квест принимает значение false, т.е. не взят ;
MP.quest = false; // название квеста не будет отображаться на экране ;
MP.MissionText = ""; // убирается название квеста;
MP.ObjectTag = ""; // обнуляется тэг объекта;
MP.MissionObjects = false; // объект считается не подобранным;
vis = false; // диалоговое окно закрывается;
}
}
else
{ // если вы еще не подобрали объект;
if (GUI.Button(new Rect((Screen.width — 100) / 2, (Screen.height — 300) / 2 + 250, 100, 40), «Нет»)) // то вместо кнопки да, будет кнопка нет;
{
vis = false; // при нажатии на которую, окно просто закроется;
}
}
}
}
}
}

Этот скрипт мы добавляем к NPC_01, так как я решил, что именно он будет давать нам квест!

Ну и, соответственно, нам необходим предмет, который мы будем искать по квесту. У меня это меч, который я также взял из папки префаб и аккуратно поместил его возле повозки.

Создаём скрипт Sword:

Скрипт Sword

using UnityEngine;
using System.Collections;

public class Sword: MonoBehaviour

{
private Quest MP; // опять подключаем скрипт Quest;

void Start()
{
MP = GameObject.FindGameObjectWithTag(«Player»).GetComponent<Quest>();
} // определяем что скрипт Quest будет находится на персонаже с тэгом player;
void OnMouseUp()
{
if (Input.GetMouseButtonUp(0)) // если при нажатии на правую кнопку мыши;
{
if (MP.ObjectTag == gameObject.tag) // и при том что тэг объекта равен тому значению которое написано в ObjectTag;
{
MP.MissionObjects = true; // то переменная принимает значение true, т.е. считается что предмет собран;
Destroy(gameObject); // и удаляем этот объект со сцены;
}
}
}
}

Добавляем скрипт к нашему мечу, и теперь необходимо создать для него тег Sword. В Inspector нажимаем на Tag выбираем Add Tag, жмём на плюсик и прописываем название Sword. Готово, тег Sword готов. Возвращаемся к NPC_01, смотрим Inspector, видим наш NPC(Script) и в строке Mission Tag прописываем sword. Если всё сделано правильно, то у нас появился наш первый квест! Давайте проверим как он работает.Запускаю игру, подхожу к НПЦ и нажимаю клавишу Е (именно она прописана в скрипте как клавиша вызова диалога).

НПЦ дал наш первый квест! Нажимаю ОК и отправляюсь на поиски меча. Как видим, у нас появилась надпись, оповещающая нас, какой именно квест мы сейчас проходим в левой части экрана.

Подойдя к мечу, нажимаю на него, и он пропадает, что говорит о правильной работе скрипта! И также появляется надпись, что мы выполнили квест, а значит нужно возвращаться и отдать меч стражнику.

Вернувшись к стражнику, он задаёт вопрос, я на него отвечаю, и вижу что квест выполнен, YoHOO!

Наш первый выполненный квест в этом мире, теперь мы настоящий герой! Но остался другой вопрос, ведь квест мы выполнили, а охранник обещал нас пропустить. Теперь необходимо сделать анимацию открывающейся решетки, чтобы она открывалась, как только мы выполняем квест. Для этого выбираем нашу решетку и заходим во вкладку Animation (если у Вас её нет, то зайдите в Window -> Animation -> Animation и у Вас появится эта вкладка либо нажмите Ctrl+6). Решетку я назвал Door_01 и теперь во вкладке Animation давайте сделаем анимацию поднятия решетки. Нажимаем Create и я ставлю название DoorOpen. Далее я выбираю кадр 0:55 нажимаю на красную кнопку, а после поднимаю решетку, снова нажимаю на красную кнопку, и вот у нас есть ключи анимации как поднимается решетка.

Создаю еще одну анимацию, но на этот раз решетка находится внизу, и сохраняю её как DoorClose. После захожу в Animator, и подключаю анимацию, как мы это делали уже множество раз. Проверяю и вижу, что анимация работает, решетка непрерывно открывается =).

 Ну что же, вперед к финишной прямой сегодняшней статьи =). Первым делом создаю очередной скрипт OpenDoor.

Скрипт OpenDoor

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

public class OpenDoor: MonoBehaviour
{
private Quest MP; // подключаем скрипт Quest;

void Start()

{
MP = GameObject.FindGameObjectWithTag(«Player»).GetComponent<Quest>(); // определяем что скрипт Quest будет находится на персонаже с тэгом player;
}


void Update()
{
if (MP.Money == 100)
{
GetComponent<Animator>().SetBool(«ODoor», true);
}
}
}

Это единственный скрипт, что я нашел в интернете, который мне подошел. Я конечно его немного подправил под мои нужны в виде MP.Money. А для того, чтобы эта строчка работала, необходимо подключить скрипт Quest, что мы и сделали в самом начале. В скриптах, что я нашел ранее, есть параметр, который даёт вознаграждение в виде денег за выполнение квеста, поэтому мы добавим одну строчку, которая нам даст 100 монет, на которые и будет отвечать скрипт открывающий решетку.

Добавляем строчку в скрипт NPC
if (GUI.Button(new Rect((Screen.width — 100) / 2, (Screen.height — 300) / 2 + 250, 100, 40), «Да»)) // то появится кнопка да, при нажатии на которую;
{
quest = false; // переменная квест принимает значение false, т.е. не взят ;
MP.quest = false; // название квеста не будет отображаться на экране ;
MP.MissionText = ""; // убирается название квеста;
MP.ObjectTag = ""; // обнуляется тэг объекта;
MP.MissionObjects = false; // объект считается не подобранным;
MP.Money = MP.Money + 100;
vis = false; // диалоговое окно закрывается;

}

После всех манипуляций, добавляем наш скрипт OpenDoor на объект решетки, и вперед тестить!

После того как я сдал квест и получил свои 100 монет, решетка открылась =). На этом я думаю на сегодня хватит, продолжение будет скоро!

Заключение

Очередной этап создания игры закончен, абсолютно всё, что я тут проделал было взято из уроков или статей интернета.

Я конечно многое бы сделал по другому, но эксперимент есть эксперимент, и с каждой статьёй мне кажется игру я всё же закончу. Всегда рад Вашим комментариям, увидимся в следующей статье!

ПС

Большинство роликов на ютубе были абсолютно бесполезны! Зря потраченное время =).

Автор не входит в состав редакции iXBT.com (подробнее »)

6 комментариев

Добавить комментарий

110097281221967604426@google
Вообще с тех. части это сцена)
Icy
Я же в буду использовать префабы, которые шли в комплекте с персонажем, а Terrain послужит мне границами уровня. (Для тех кто всё же хочет, чтобы я создал игровую область без префабов, пишите в комментариях, тогда будет понятно, нужна ли такая информация)

Это общая практика, что префабы дают вместе с моделью персонажа? Если вас не затруднит, какие-то базовые инструкции по созданию ландшафта с нуля были бы интересны.
Вообще, спасибо за серию статей, вы молодец.
182749768@vkontakte
Префабы не всегда бывают в паке. Надо читать что внутри ассет пака, перед покупкой, а то могут быть и без текстур, и без анимации или просто «статуи». У некоторых авторов ассетов есть видео на ютубе, где они показывают содержимое своих ассетов. Если вдруг, есть много свободного времени, то советую посмотреть обучающие ролики по 3D моделированию и анимации, вдруг вам будет достаточно начальных навыков и не придётся покупать ассеты.
n
Хорошо, как будет свободная минута напишу статью по Terrain
115198768158955650649@google
Выдает ошибку cant add script component «NPC» because the script class cannot be found.Make sure that found. такая же ошибка и с Sword.Помогите что делать? не могу разобраться
115198768158955650649@google
Выдает ошибку cant add script component «NPC» because the script class cannot be found.Make sure that found. такая же ошибка и с Sword.Помогите что делать? не могу разобраться, таже самая ошибка и с Quest, хотя тэги на всем поставил.

Добавить комментарий

Сейчас на главной

Новости

Публикации

«Бумажные города»: почему картографы десятилетиями рисуют места, которых не существует

Представьте такую ситуацию: вы едете по навигатору вглубь штата Нью-Йорк, ищете небольшой городок под названием Эглоу. Карта уверенно ведет вас к пересечению двух дорог, обещая заправку и пару...

Инженеры поместили волонтера в комнату с сотнями комаров, чтобы создать самую точную модель их охоты

Комары вида Aedes aegypti являются переносчиками тяжелых заболеваний, таких как желтая лихорадка, лихорадка денге и вирус Зика. Ежегодно эти болезни приводят к летальным исходам по всему миру....

Край миллиона молний: почему небо над озером Маракайбо никогда не бывает спокойно

На данный момент Венесуэла, конечно, не самое гостеприимное место, но в нем есть одна локация, которую просто невозможно пропустить, ведь второго такого феномена на всей нашей голубой планете не...

До остывания Вселенной привычной гравитации не существовало: как новая квантовая модель избавила Большой взрыв от сингулярности

Общая теория относительности Альберта Эйнштейна до сих пор остается самым точным инструментом для описания гравитации на макроскопическом уровне. Она безошибочно рассчитывает орбиты планет,...

Кварцевые часы, которые остроумно имитируют механические: обзор «винтажной» модели Undone

Если рассмотреть ассортимент этого бренда, то станет очевидно: вдохновение Undone черпает в винтажных часах. И, справедливости ради, у него получается. Компания точно попадает в цвет,...

Обзор соковыжималки для цитрусовых RAWMID Mini RMJ-02: апельсиновый сок дома за 20 секунд

Свежевыжатый сок в домашних условиях — это не только полезно, но и довольно просто, а с соковыжималкой RAWMID Mini RMJ-02 процесс становится ещё и по-настоящему быстрым и удобным. В этом...