Как сделать монолог в unity

Обновлено: 03.07.2024

Как сделать многоуровневую игру в Unity? Или игру, в которой игрок может перемещаться (телепортировать) между локациями?

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

Шаг 1. Создать сцены для каждого уровня и пр. составляющих игры. Продумать понятную и гибкую систему идентификации файлов сцен

Например, сцены могут иметь следующие имена:

  • StartScene – стартовая сцена игры. Это может быть сцена, в которой игрок знакомится с правилами игры, может изменить некоторые начальные настройки, выбрать персонажа и т.д.
  • Layer1,Layer2,Layer3, … — сцены, соответствующие 1-му, 2-му, 3-му и т.д. уровням игры.
  • EndGame – конечная сцена, которая загружается в финале игры.

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

Например, следующий уровень может загружаться при следующих возможных условиях:

а) игрок набрал определённое количество баллов. Это условие имеет смысл проверять каждый кадр в методе Update();

б) игрок добрался до определенного места в игре. Например, пришёл к заданной двери. Соответственно на объекте двери необходимо поставить коллайдер, и при входе в этот коллайдер должна будет выполняться загрузка сцены;

Family Island - меню выбора островов для путешествий и приключений

Family Island — меню выбора островов для путешествий и приключений

Когда речь идёт не столько об уровнях игры, сколько о разных локациях, между которыми игрок имеет возможность перемещаться. Пример такой игры – Family Island – там игрок может путешествовать на различные острова.

Candy Crush Saga — карта игры с выбором уровней

Второй вариант геймплея с аналогичным функционалом – наличие в реализации отдельной сцены с картой игры. Кликая по определённым зонам-кнопкам этой игры, игрок загружает соответствующий уровень (при условии, что этот уровень для него открыт). Наиболее популярный пример такой игры – Candy Crush Saga и ей подобные.

Шаг 3. Написание функции (метода) загрузки соответствующей сцены.

Для загрузки сцен в движке Unity предусмотрен метод LoadScene (…) из класса SceneManager пространства имён UnityEngine.SceneManagement.

Это значит, что в классе (скрипте), в котором будет выполняться загрузка сцены с помощью указанного метода, должна быть прописана директива:

Далее, при вызове метода следует указывать и имя класса:

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

Наиболее простые способы вызова метода следующие.

Вариант 1 – с явным указанием имени загружаемой сцены в качестве параметра. Например:

Вариант 2 – с указанием индекса загружаемой сцены в качестве параметра. Например:

Индекс – это число-порядковый номер сцены, который автоматически присваивается в окне настроек Build Settings:

Окно настроек Build Settings Unity

Окно настроек Build Settings

Один из возможных вариантов скрипта следующий:

Этот скрипт должен быть на объектах-дверях или телепортах. На них же должен стоять коллайдер-триггер.

Шаг 4. Заполнить раздел Scenes In Build в окне настроек Build Settings, внеся туда все сцены, которые необходимо будет загружать

Пример этого окна представлен выше. Чтобы его вызвать, используется главное меню, пункты File -> Build Settings...


Меню File -> Build Settings… Unity

Вам когда-либо приходилось думать над тем, как сделать управление сценами в вашем проекте менее болезненным? Когда у вас достаточно простая игра, в которой всего несколько сцен идущих одна за другой, то, зачастую, всё проходит гладко. Но когда количество сцен растёт и усложняются переходы между ними — они могу загружаться в разном порядке и поведение некоторых из них должно зависеть от входящих параметров — задача становится менее тривиальной.

Ниже несколько подходов к ее решению, которые мне приходилось видеть чаще всего:

  • Файлы — при переходе из одной сцены в другую, все необходимые данные записываются в JSON/XML файл, а когда следующая сцена загрузилась, считывают их обратно. Как минимум, это медленно (говоря о чтении и записи в файл), да и процесс дебага становится менее удобным.
  • Огромный статический класс, который обрабатывает все возможные переходы между сценами. Они очень похожи на божественные объекты и довольно часто являются причиной утечек памяти, а также боли в нижней части спины, когда новый разработчик пытается понять, что вообще происходит в этой тысяче строк статического кода.
  • DontDestroyOnLoad GameObject — этот подход похож на предыдущий, но представлен GameObject'а в сцене с кучей ссылок в Инспекторе. По сути, это один из тех синглтонов, которые каждый из нас видел в большинстве проектов.

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

В каждой сцене у меня есть SceneController . Он отвечает за проброс всех необходимых ссылок и инициализацию ключевых объектов. В некотором смысле, его можно считать точкой входа сцены. Для представления аргументов я использую класс SceneArgs и у каждой сцены есть свой класс, представляющий ее аргументы и являющийся наследником SceneArgs .

Как я уже написал выше, у каждой сцены есть свой контроллер, который наследуется от SceneController .

Я использую отдельный класс для представления аргументов по одной простой причине. Изначально, метод загрузки сцены принимал аргументы в виде массива объектов params object[] args . Это был унифицированный способ для загрузки любой сцены с возможностью передать аргументы. Когда контроллер сцены получал управление, он парсил этот массив объектов и получал все необходимые данные. Но, кроме банального боксинга, здесь была ещё одна проблема — ни для кого, кроме разработчика, который писал этот контроллер (а со временем и для него самого) не было очевидно, какого типа аргументы и в каком порядке нужно передать, чтобы потом не возникло ошибок кастинга. Когда мы создаём новый метод, то в его сигнатуре указываем порядок и типы аргументов и затем IDE может нам подсказать, если при его вызове мы допустили ошибку. Но с аргументом params object[] args мы видим лишь то, что нужно передать массив аргументов и каждый раз, чтобы понять их порядок и типы, разработчику нужно лезть в код контроллера и смотреть как же они парсятся. Мне хотелось сохранить метод запуска таким же унифицированным (один метод для запуска любой сцены), но при этом дать возможность жестко ограничить типы аргументов для каждой из сцен. И для этого нужны ограничения where , которые есть в SceneController .

Как известно, мы должны каждый раз передавать name или buildIndex сцены, чтобы загрузить её через метод LoadScene() или LoadSceneAsync() в Unity API. Этого хотелось бы избежать, потому я использую кастомный атрибут SceneControllerAttribute , чтобы привязать конкретный контроллере к конкретной сцене. Здесь используется имя сцены, а не её buildIndex лишь по той причине, что, на моём опыте, оно реже подвергается изменениям.

Допустим, у нас есть сцена MainMenu . В таком случае, классы её аргументов и контроллера будут иметь следующий вид:

Собственно, это всё (из того, что касается контроллера сцены и её аргументов). Осталось лишь понять, как происходит переход от одной сцены к другой. Этим занимается внезапно статический класс SceneManager . Очень важно, чтобы он был как можно меньше, проще и понятнее. Чтобы он не превратился в один из тех ненавистных божественных объектов с тоннами зависимостей. У него всего лишь одна простая задача — передать управление от контроллера одной сцены к контроллеру следующей. За все последующие инициализации и прочее отвечает уже сам контроллер.

Позвольте мне немного объяснить этот код. При вызове OpenSceneWithArgs() вы передаёте тип контроллера ( TController ) сцены, которую нужно загрузить, тип параметров ( TArgs ) и, собственно, сами параметры ( sceneArgs ). В первую очередь, SceneManager проверяет, есть ли у TController атрибут SceneControllerAttribute . Он должен быть, потому именно он определяет, к какой сцен привязан контроллер TController . Дальше мы просто добавляем аргументы sceneArgs в словарь. Если не было передано каких-либо аргументов, мы создаём экземпляр типа TArgs и присваиваем его свойству IsNull значение true . Если всё прошло гладко, то будет вызван метод из Unity API LoadSceneAsynс() и ему будет передано имя сцены, которое берётся из атрибута SceneControllerAttribute .

Загружается следующая сцена и у её контроллера вызывается метод Awake() . Дальше, как видим в SceneController , TController вызывает SceneManager.GetArgs() , чтобы получить аргументы, которые были переданы и записаны в словарь, а затем производит все необходимые инициализации.

В результате у нас каждая сцена сама отвечает сама за себя, а переходы происходят через небольшой класс SceneManager , отвечающий исключительно за передачу управления между ними. Просто попробуйте применить этот подход в одном из ваших пет проектов и вы заметите, на сколько прозрачнее и понятнее для вас и всех кто работает с вами станут переходы между сценами и их инициализации. Буду рад вашим комментариям. Успехов в разработке!

Прежде чем начать, рассмотрите возможность использования подключаемого модуля Unity для пакета SDK служб распознавания речи. У подключаемого модуля есть лучшие результаты для распознавания речи и простой доступ к декодированию речи в текст, а также расширенные функции речи, такие как диалоговое окно, взаимодействие на основе намерений, перевод, синтез текста в речь и распознавание речи на естественном языке. Чтобы приступить к работе, ознакомьтесь с примером и документацией.

Unity предоставляет три способа добавления речевого ввода в приложение Unity, первые два из которых являются типами фрасерекогнизер:

  • KeywordRecognizer Предоставляет приложению массив строковых команд для прослушивания
  • GrammarRecognizer Предоставляет приложению файл SRGS, определяющий конкретную грамматику для прослушивания
  • DictationRecognizer Позволяет приложению прослушивать любое слово и предоставлять пользователю заметку или другое отображение речи

Диктовка и распознавание фраз не могут быть обработаны одновременно. Если Граммаррекогнизер или Кэйвордрекогнизер активен, Диктатионрекогнизер не может быть активным и наоборот.

Включение возможности для голоса

Для использования речевого ввода приложение должно быть объявлено с помощью функции микрофона .

  1. в редакторе Unity перейдите к изменению > Project Параметры > Player .
  2. выберите вкладку " хранилище Windows ".
  3. в разделе Параметры > возможностей публикации проверьте возможность использования микрофона .
  4. предоставление разрешений приложению доступа к микрофону на устройстве HoloLens
    • Вам будет предложено сделать это при запуске устройства, но если вы случайно щелкнули "нет", вы можете изменить разрешения в параметрах устройства.

Распознавание фраз

Чтобы разрешить приложению прослушивать определенные фразы, произносимые пользователем, выполните некоторые действия:

  1. Укажите, какие фразы следует прослушивать с помощью KeywordRecognizer или GrammarRecognizer
  2. Обрабатывает OnPhraseRecognized событие и принимает действие, соответствующее распознанной фразе

кэйвордрекогнизер

Пространство имен: UnityEngine. Windows. Речь
Типы: кэйвордрекогнизер, фрасерекогнизедевентаргс, спичеррор, спичсистемстатус

Чтобы сохранить несколько нажатий клавиш, потребуется несколько операторов using:

Затем добавим несколько полей в класс для хранения словаря распознавателя и ключевого слова >.

Теперь добавьте в словарь ключевое слово, например в Start() методе. В этом примере мы добавляем ключевое слово "Activate":

Создайте распознаватель ключевых слов и сообщите ему, что мы хотим узнать:

Теперь Зарегистрируйтесь для OnPhraseRecognized события

Наконец, начните распознать!

граммаррекогнизер

Пространство имен: UnityEngine. Windows. Речь
Типы: граммаррекогнизер, фрасерекогнизедевентаргс, спичеррор, спичсистемстатус

Граммаррекогнизер используется, если вы указываете грамматику для распознавания с помощью SRGS. Это может быть полезно, если приложение содержит несколько ключевых слов, если вы хотите распознавать более сложные фразы или хотите легко включать и выключать наборы команд. Сведения о формате файла см. в статье Создание грамматик с помощью XML-кода SRGS .

После того как грамматика SRGS будет доступна в проекте в папке стреамингассетс:

Создайте GrammarRecognizer и передайте ему путь к файлу SRGS:

Теперь Зарегистрируйтесь для OnPhraseRecognized события

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

Наконец, начните распознать!

Диктовка

Пространство имен: UnityEngine. Windows. Речь
Типы: диктатионрекогнизер, спичеррор, спичсистемстатус

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

  1. Создать новый DictationRecognizer
  2. Обработку событий диктовки
  3. Запуск Диктатионрекогнизер

Включение функции для диктовки

Для использования режима диктовки в приложении необходимо объявить клиент Интернета и возможности микрофона .

  1. в редакторе Unity выберите изменить > Project Параметры > Player .
  2. выберите на вкладке " хранилище Windows "
  3. в разделе Параметры > возможностей публикации проверьте возможность использования функции InternetClient .
    • Кроме того, если микрофон еще не включен, проверьте возможность использования микрофона .
  4. предоставьте разрешения на доступ к микрофону для приложения на устройстве HoloLens, если вы еще не сделали этого.
    • Вам будет предложено сделать это при запуске устройства, но если вы случайно щелкнули "нет", вы можете изменить разрешения в параметрах устройства.

диктатионрекогнизер

Создайте Диктатионрекогнизер следующим образом:

Существует четыре события диктовки, которые можно подписывать и обрабатывать для реализации поведения диктовки.

  1. DictationResult
  2. DictationComplete
  3. DictationHypothesis
  4. DictationError

диктатионресулт

Это событие возникает после приостановки пользователем, как правило, в конце предложения. Здесь возвращается полная распознанная строка.

Сначала Подпишитесь на DictationResult событие:

Затем обработайте обратный вызов Диктатионресулт:

диктатионхипосесис

Это событие возникает постоянно во время разговора пользователя. Как распознаватель прослушивает этот момент, он предоставляет текст о том, что он слышал.

Сначала Подпишитесь на DictationHypothesis событие:

Затем обработайте обратный вызов Диктатионхипосесис:

диктатионкомплете

Это событие возникает при остановке распознавателя, при вызове из метода Stop (), истечения времени ожидания или при возникновении какой-либо другой ошибки.

Сначала Подпишитесь на DictationComplete событие:

Затем обработайте обратный вызов Диктатионкомплете:

диктатионеррор

Это событие возникает при возникновении ошибки.

Сначала Подпишитесь на DictationError событие:

Затем обработайте обратный вызов Диктатионеррор:

После подписки и обработки событий диктовки запустите распознаватель диктовки, чтобы начать получать события.

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

Советы

  • Start() методы и, Stop() соответственно, включают и отключают распознавание диктовки.
  • После завершения с распознавателем его необходимо удалить с помощью, Dispose() чтобы освободить используемые ресурсы. Он автоматически освобождает эти ресурсы во время сборки мусора при дополнительных затратах на производительность, если они не выявляются до этого.
  • Время ожидания происходит по истечении заданного периода времени. Эти времена ожидания можно проверить в DictationComplete событии. Существует два времени ожидания, которые следует учитывать:
    1. Если распознаватель запускается и не слышит звук в течение первых пяти секунд, время ожидания истекает.
    2. Если распознаватель предоставил результат, а затем слышит бездействия в течение 20 секунд, время ожидания истечет.

Использование распознавания и диктовки фраз

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

Можно вызвать Restart() для восстановления всех распознавателей до их предыдущего состояния после остановки диктатионрекогнизер:

Кроме того, можно просто запустить Кэйвордрекогнизер, который также перезапустит Фрасерекогнитионсистем.

ввод голоса в смешанной реальности набор средств

Примеры МРТК для речевого ввода можно найти в следующих демонстрационных сценах:

Следующий этап разработки

Если вы используете точку контрольной точки разработки Unity, которую мы собрали, то вам следует ознакомиться с возможностями и API платформы смешанной реальности:

Приветствую всех друзья! В прошлой статье я закончил обзор основного интерфейса Unity, подробно рассмотрев окно сцены. Сегодня мы поговорим о сценах и игровых объектах более подробно, так как это фундаментальные вещи, которые понадобятся для создания игры.

Unity дает возможность делать игры большому кругу людей заинтересованных в этом. Главной особенностью является то, что вам не нужны годы работы программистом или художником, чтобы начать делать небольшие и интересные игры. Существует несколько основных концепций рабочего процесса в Unity, которые необходимо понять. Однажды выучив и поняв их, вы будете делать игры в кратчайшие сроки. А то время что вы будете экономить – можно потратить на оттачивание и балансировку игры. Первые две концепции о которых я расскажу – это концепция сцены и игрового объекта.

Сцены.

Сцены содержат в себе меню и игровое окружение вашей игры. Они состоят из игровых объектов, о которых мы поговорим ниже. Думайте о каждой новой сцене как о новом уровне в своей игре. В каждой сцене вы размещаете окружение, украшения, препятствия, меню и прочее-прочее, по сути собирая свою игру по кусочкам (уровням).

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

Для того чтобы сохранить сцену необходимо либо в контекстном меню выбрать File/Save Scene , либо сочетанием клавиш Ctrl+S (Windows) и Cmd+S (Mac). Unity сохраняет ваши сцены как ассеты в папке Assets по умолчанию, но я рекомендую сделать внутри папки Assets отдельную папку для сцен и хранить их там. Это также значит, что ваши сцены вы можете увидеть в окне проекта, как и любой другой ресурс игры.

Открыть сцену можно двойным нажатием левой кнопки мыши в окне проекта по ранее сохраненному файлу сцены. Если при этом вы забыли сохранить текущую сцену – Unity спросит вас стоит ли это сделать перед ее закрытием.

Игровые объекты.

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

Чтобы наш игровой объект стал деревом, светом или врагом – необходимо придать ему свойства. Свойства мы придаем компонентами (в прошлой статье я уже касался этой темы и объяснял, что такое компонент в Unity). В зависимости от того, какой игровой объект вы хотите создать, вы добавляете необходимые для этого компоненты. Можно также представить игровой объект как пустую кастрюлю, а компоненты ингредиентами, составляющими рецепт вашей игры. Unity имеет большое количество готовых компонентов, а также есть возможность создавать свои с помощью написания пользовательских скриптов (это очень обширная тема которую я еще затрону в будущих статьях).

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

Компоненты можно добавлять, удалять или изменять на игровом объекте. Для того чтобы добавить игровому объекту компонент, выберите его и нажмите на кнопку Add Component , в появившемся выпадающем меню выберите необходимый компонент и добавьте его. Чтобы удалить компонент с игрового объекта нажмите в окне инспектора на его название правой кнопкой мыши, появится контекстное меню, в котором необходимо выбрать пункт Remove Component .

Чтобы изменять параметры компонента, нужно выбрать необходимое поле в окне инспектора и ввести туда необходимые данные (например, для компонента Transform мы можем ввести координаты расположения игрового объекта). Также через контекстное меню мы можем копировать компоненты и вставлять их на другие игровые объекты, а если на нем уже был такой компонент, то он предложит одно из двух действий, либо вставить его как новый, либо просто копировать значения из копируемого компонента в тот что висит на игровом объекте.

Unity поддерживает работу с любыми 3D объектами созданными в стороннем программном обеспечении, но также она умеет сама создавать такие примитивные объекты как куб, сфера, капсула, цилиндр и плоскость. Эти объекты часто используются для быстрого прототипирования игр. Чтобы создать любой из них пройдите в контекстное меню GameObject/3D Objects и выберите любой из них. Тоже самое можно сделать в окне иерархии нажав на пустое место правой кнопкой мыши и выбрав пункт 3D Object .

Как я уже писал немного выше компонент Transform является единственным компонентом, который нельзя удалить с игрового объекта. Давайте посмотрим на его параметры немного более подробно:

1. Position – это позиция нашего игрового объекта в сцене в XYZ координатах

2. Rotation – это вращение нашего игрового объекта в сцене, оно также задается в XYZ, но это уже не координаты, а оси по которым мы поворачиваем наш объект в градусах.

3. Scale – это размер нашего игрового объекта в сцене. По умолчанию он равен 1. Меняется он также по всем 3 осям.

Любой игровой объект можно включить или выключить либо через галочку что на картинке выше (ее можно найти в окне инспектора), либо через код. Когда мы отключаем игровой объект все его компоненты перестают работать. Также если у этого игрового объекта были вложенные объекты (дети), то при его отключении они также перестают функционировать.

Чтобы добавить новый тег нужно выбрать в конце списка пункт Add Tag в открывшемся окне инспектора нажмите + и впишите свой тег. Теперь он есть в списке тегов. Также в Unity по умолчанию уже присутствует несколько тегов (например MainCamera, для определения главной камеры на сцене).

Если игровой объект статично стоит на сцене и никуда не перемещается – то это статический объект. Если же он движется во время выполнения игры – это динамический объект.

Когда вы помечаете игровой объект как статический (галочка напротив пункта Static ), при условии, что он не будет двигаться во время выполнения – такой объект будет экономить вычислительные мощности игрока, так как Unity автоматически оптимизирует работу с такими игровыми объектами.

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

После работы со сценой и проектом в целом не забывайте сохранять изменения. В Unity сохранения делятся на 2 вида:

1. Это сохранение самой сцены

2. Это сохранение различных настроек проекта, а также ассетов и настроек в них

Как сохранить сцену я писал выше. А для сохранения проекта в любой момент выберите в контекстном меню File\Save Project . Также не забывайте – когда вы открыли префаб для редактирования – любое сохранение (как проекта, так и сцены) сохранит изменения в префабе.

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

Читайте также: