Создание визуальной новеллы в Unity 6 (1/10)
Если вам нравятся визуальные новеллы игры, то в данном цикле уроков я вам покажу как при помощи скриптового языка Ink создать простой текстовый квест, с системой диалогов, ветвлением сюжета, а так же обернем его в красивую обертку аниме тяночек при помощи нейросети.
Делать я это буду по примеру своей игры URNext, которая скоро появится в раннем доступе, а дневник ее разработки я буду выкладывать у себя здесь на канале. Она будет несколько сложнее чем этот учебный материал, и на ее примере я буду показывать с каким сложностями я столкнулся и как решил по мере разработки. Но это отдельная история здесь же все у нас будет просто и понятно. Все для того чтобы вы могли легко это повторить и сделать свой проект.
Итак ink. Скриптовый язык, который ребята из Inkle Studios создали, чтобы легче было разрабатывать свои текстовые игры. Самое приятное, что он с открытым исходным кодом и бесплатен для использования!
Ink позволяет легко писать истории с разветвленным повествованием, выбором и диалогами. В комплект поставки входит Inky - редактор, в котором вы можете писать истории на движке Ink, отлаживать их и запускать в том же окне, чтобы проверить варианты и т.д. Есть также InkleWriter, который предлагает простой интерфейс, позволяющий создавать эти истории без необходимости углубляться в скриптовую магию. Честно говоря, я им не пользовался. Если ваша единственная цель - написать интерактивную фантастику и поделиться ею, возможно, вам стоит попробовать. Однако если вы планируете создать с помощью Unity настоящую сюжетно-ориентированную игру, прошу под кат.
Работа с Ink
Inkle предлагает чрезвычайно полную документацию с примерами использования движка Ink и всех его возможностей. Есть также пример игры, в которой эти функции показаны в действии. Однако, я вам подготовил этот небольшой пример, чтобы показать вам основы того как сделать минимально рабочий проект с Ink в Unity.
Так что качайте Inky и приступайте к работе.
Узлы
Основа основ это узлы - Knots. Представьте их как сцены внутри вашего рассказа. В каждой сцене может быть диалог, абзац текста, несколько вариантов действий и т.д. Вы сами решаете, как вы хотите структурировать свою историю. Как вариант, можно переходить к другому узлу, когда мы делаем выбор, меняем сцену или когда меняется контекст (например, игроку нужно выполнить действие). Узлы в тексте обозначают следующим образом:
=== knot_title ===
Далее идет содержание узла
Тут все просто! Но я сказал, что история строится из нескольких узлов, поэтому вам понадобится способ перемещаться между ними. Делается это следующим образом:
содержание узла
-> knot_title
Это также используется для того, чтобы указать ink, какой узел является точкой входа в вашу историю, поэтому убедитесь, что вы добавили эту строку в начало вашего скрипта (с правильным названием). Это очень важно, так как иначе Ink не будут знать, с чего начать!
А теперь давайте посмотрим пример сценария.
-> start_knot // Это говорит движку ink с какого узла начать
=== start_knot ===
Здарова заебал! Это стартовый узел.
А теперь мы можем перейти к узлу 2!
-> knot_2
=== knot_2 ===
Вот мы и в узле номер 2!
-> END // Так помечается конец истории
Вы увидите, что knot_2 заканчивается строкой -> END. Это нужно для того, чтобы отметить, где заканчивается история.
Вы должны убедиться, что все ваши узлы имеют конец, будь то переход к следующему узлу или завершение истории (Inky напомнит вам и об этом).
Итак, перейдем к самому интересному - выбору. В своей игре вы, скорее всего, захотите дать игроку возможность принять решение.В зависимости от того, что он выберет, мы захотим разветвиться на разные узлы. Как же это сделать?
*** Выбор 1
[Продолжение для выбора 1]
*** Выбор 2
[Продолжение для выбора 2]
Каждый выбор отмечен ***, и то, что следует за ним, будет видно только после того, как игрок выберет этот вариант.Давайте добавим это в наш пример:
-> start_knot // Это говорит движку ink с какого узла начать
=== start_knot ===
Здарова заебал! Это стартовый узел.
А теперь мы можем перейти к узлу 2!
-> knot_2
=== knot_2 ===
Вот мы и в узле номер 2!
Пришло время выбора
Кого ты выберешь? Рыженькую или блондиночку?
*** Рыженькую
Да, она горяча, но у рыжих нет души!
-> END // Так помечается конец истории
*** Блондиночку
Хороший выбор мой друг!
-> END // Так помечается конец истории
Теперь вы видите, что каждый выбор имеет свое продолжение, и мы выполнили наше первое разветвление! Вы можете проверить свою историю в Inky, в правой части окна.
Вы можете себе представить, что это может стать довольно сложным для чтения (и написания), если вы добавите много текста для каждого выбора. Поэтому, как уже говорилось выше, можно разбить текст на дополнительные узлы после каждого решения, чтобы было легче с ним справиться. Давайте изменим наш пример:
-> start_knot
=== start_knot ===
Здарова заебал! Это стартовый узел.
А теперь мы можем перейти к узлу 2!
-> knot_2
=== knot_2 ===
Вот мы и в узле номер 2!
Пришло время выбора
Кого ты выберешь? Рыженькую или блондиночку?
*** Рыженькую
-> рыженькая
*** Блондиночку
-> блондиночка
=== рыженькая ===
Да, она горяча, но у рыжих нет души!
-> END
=== блондиночка ===
Хороший выбор мой друг!
-> END
Теперь вы видите, что у каждого варианта есть свой узел. С точки зрения игрока ничего не изменилось. Тем не менее, такой подход может оказаться очень полезным при локализации игры (никогда не знаешь, когда это может понадобиться!) и даже просто для того, чтобы сделать ее более читабельной и удобной в работе.
Выбор имеет значение
Мы узнали, как разветвлять сюжет на основе различных вариантов, но в основном вам все равно захочется придерживаться одной определенной линии сюжета. В противном случае история может очень быстро выйти из-под контроля. Если вы хотите это сделать, просто создайте новый узел и укажите на него из выбранных вами конкретных узлов.
-> start_knot
=== start_knot ===
Здарова заебал! Это стартовый узел.
А теперь мы можем перейти к узлу 2!
-> knot_2
=== knot_2 ===
Вот мы и в узле номер 2!
Пришло время выбора
Кого ты выберешь? Рыженькую или блондиночку?
*** Рыженькую
-> рыженькая
*** Блондиночку
-> блондиночка
=== рыженькая ===
Да, она горяча, но у рыжих нет души!
-> продолжаем
=== блондиночка ===
Да, она горяча, но у рыжих нет души!
-> продолжаем
=== продолжаем
Ну лан. Ты ответил на мой вопрос.
-> END
-> start_knot
=== start_knot ===
Hello from the start knot!
Now we'll go to knot 2!
-> knot_2
=== knot_2 ===
Hello from knot 2!
Time for a personality test.
Red pill or blue pill?
*** Red pill
-> red_pill
*** Blue pill
-> blue_pill
=== red_pill ===
My god, how brave!
-> continue_conversation
=== blue_pill
Bold move, my friend
-> continue_conversation
=== continue_conversation
Alright. You have answered my question.
-> END
Все просто! Эти варианты должны иметь значение. Например, что если мы хотим сделать комментарий на основе того, что сделал игрок? Самый простой способ - проверить, посетили ли мы определенный узел или нет (хе-хе!). Вот как сделать такую проверку:
{ имя_узла: [дальнейшее содержание сюжета] }
Хотите проверить, не посещали ли мы узел?
{ not knot_name: [дальнейшее содержание рассказа] }
Используя этот паттерн, вы можете проверять множество различных условий и определять поток истории соответствующим образом. Давайте посмотрим на него в действии:
-> start_knot
=== start_knot ===
Hello from the start knot!
Now we'll go to knot 2!
-> knot_2
=== knot_2 ===
Hello from knot 2!
Time for a personality test.
Red pill or blue pill?
*** Red pill
-> red_pill
*** Blue pill
-> blue_pill
=== red_pill ===
My god, how brave!
-> continue_conversation
=== blue_pill
Bold move, my friend
-> continue_conversation
=== continue_conversation
Alright. You have answered my question.
{ red_pill:
You chose the red pill. But I'm still not sure I can trust you
}
{ not red_pill: -> no_red_pill_comment}
->END
=== no_red_pill_comment ===
You didn't choose the red pill. I'm not sure I can trust you.
-> END
Вы заметите, что я использовал оба подхода: вводил текст сразу после проверки и указывал на другой узел. Вы сами решаете, как структурировать свой файл и что для вас удобнее. Просто имейте в виду, что использование узлов может очень помочь в дальнейшем.
В следующем уроке поговорим с вами о Переменных и условиях ветвления.
unity
ink
inkle
юнити
визуальная новелла
система диалогов
inky