Переход на UNIGINE с Unity: гайд для программистов
Написание игровой логики, запуск скриптов в редакторе, триггеры, ввод, рейкастинг и другое.
Специально для тех, кто ищет полноценный отечественный аналог Unity или Unreal Engine, мы продолжаем цикл статей про безболезненный переход на UNIGINE с зарубежных движков. В третьем выпуске рассмотрим миграцию с Unity с точки зрения программиста.
Общая информация
Традиционно игровая логика в проекте Unity реализуется через пользовательские компоненты — C# классы, унаследованные от MonoBehaviour. Основная логика компонента определена в событийных методах Start(), Update() и так далее.
UNIGINE предлагает очень похожую концепцию — C# Component System — стабильная и высокопроизводительная компонентная система на .NET 5. Компоненты представлены C# классами, унаследованными от Component, их можно назначить любой ноде в сцене. Жизненный цикл каждого компонента определяется набором методов (Init(), Update() и т. д.), вызываемых в основном цикле движка.
Программирование в UNIGINE с использованием C# мало чем отличается от программирования в Unity. Например, давайте сравним, как выполняется вращение объекта в Unity:
и в UNIGINE:
Кнопка для запуска экземпляра приложения в отдельном окне расположена на панели инструментов в UnigineEditor. Также рядом расположены настройки параметров запуска.
Вот как мы заставим колесо вращаться с помощью C# Component System и запустим экземпляр, чтобы немедленно его проверить:
Более того, системная логика приложения на UNIGINE может быть определена в файлах AppWorldLogic.cs, AppSystemLogic.cs и AppEditorLogic.cs в папке source проекта.
Чтобы узнать больше о последовательности выполнения и о том, как создавать компоненты, перейдите по ссылкам ниже:
Для тех, кто предпочитает C++, UNIGINE позволяет создавать приложения C++ с использованием С++ UNIGINE API, и, при необходимости, C++ Component System.
Основные примеры кода
Вывод в консоль
Используйте клавишу ~, чтобы открыть консоль в приложении
См. также:
- Дополнительные типы сообщений в API класса Log
- Видеоруководство, демонстрирующее, как выводить пользовательские сообщения в консоль с помощью C# Component System
Доступ к GameObject / Node из компонента
См. также:
- Видеоруководство, демонстрирующее, как получить доступ к нодам из компонентов с помощью C# Component System
Работа с направлениями
В Unity компонент Transform отвечает за позицию, вращение и масштаб Game Object, а также за родительско-дочерние связи. Чтобы получить вектор направления по одной из осей с учетом вращения GameObject в мировых координатах, в Unity используется соответствующее свойство компонента Transform.
В UNIGINE трансформация ноды в пространстве представлена ее матрицей трансформации (mat4), а все основные свойства и операции с иерархией нод доступны при помощи методов и свойств класса Node. Такой же вектор направления в UNIGINE получается с помощью метода Node.GetWorldDirection():
См. также:
- Система координат в UNIGINE
Более плавный игровой процесс с DeltaTime / IFps
В Unity, чтобы гарантировать, что определенные действия выполняются за одно и то же время независимо от частоты кадров (например, изменение положения один раз в секунду и т. д.), используется множитель Time.deltaTime (время в секундах, которое потребовалось для завершения последнего кадра). То же самое в UNIGINE называется Game.IFps:
Рисование отладочных данных
Unity:
В UNIGINE за вспомогательную отрисовку отвечает синглтон Visualizer:
Примечание. Visualizer также можно включить с помощью консольной команды show_visualizer 1.
См. также:
- Все типы визуализаций в API класса Visualizer.
Загрузка сцены
Доступ к компоненту из GameObject/Node
Unity:
UNIGINE:
Доступ к стандартным компонентам
Компонентный подход Unity позволяет рассматривать такие стандартные объекты, как MeshRenderer, Rigidbody, Collider, Transform и другие, как обычные компоненты.
В UNIGINE доступ к аналогам этих сущностей осуществляется иначе. Классы всех типов нод являются производными от Node, поэтому чтобы получить доступ к функциональности ноды определенного типа (например, ObjectMeshStatic), необходимо провести понижающее приведение типа (downcasting). Рассмотрим эти самые популярные варианты использования:
Unity:
UNIGINE:
Поиск GameObject/Node
Unity:
UNIGINE:
Приведение от типа к типу
Downcasting (приведение от базового типа к производному) выполняется одинаково в обоих движках с использованием родной конструкции C# as:
Чтобы выполнить Upcasting (приведение от производного типа к базовому), можно как обычно просто использовать сам экземпляр:
Уничтожение GameObject/Node
Для выполнения отложенного удаления ноды в UNIGINE можно создать компонент, который будет отвечать за таймер и удаление.
Создание экземпляра GameObject / Node Reference
В Unity экземпляр префаба или копия уже существующего в сцене GameObject создается с помощью функции Object.Instantiate:
Затем вы должны указать префаб, который будет создан, в параметрах компонента скрипта.
В UNIGINE получить доступ к уже существующей ноде любого типа можно также через параметр компонента, и клонировать ее при помощи Node.Clone().
Но ассеты не являются нодами, они принадлежат файловой системе. К ассету можно обратиться, используя эти типы параметров:
- AssetLink — для любых ассетов,
- AssetLinkNode — для ассетов *.node, содержащих иерархию нод, сохраненную как Node Reference (аналог prefab).
В этом случае ссылка на ассет, аналогично Unity, указывается в UnigineEditor:
Также можно использовать функцию World.LoadNode для загрузки иерархии нод вручную, указав виртуальный путь к ассету.
Еще один способ загрузить содержимое ассета *.node — создать NodeReference и работать с иерархией нод как с одним объектом. Тип Node Reference имеет ряд внутренних оптимизаций и тонких моментов (кэширование нод, распаковка иерархии и т.д.), поэтому важно учитывать специфику работы с этими объектами.
Запуск скриптов в редакторе
Unity позволяет расширять функциональность редактора с помощью C# скриптов. Для этого в скриптах поддерживаются специальные атрибуты:
- [ExecuteInEditMode] — для выполнения логики скрипта в режиме Edit, когда приложение не запущено.
- [ExecuteAlways] — для выполнения логики скрипта как в режиме Play, так и при редактировании.
Например, так выглядит код компонента, который заставляет GameObject ориентироваться на определенную точку в сцене:
UNIGINE не поддерживает выполнение логики C# внутри редактора. Основной способ расширить функциональность редактора — плагины, написанные на C++.
Для быстрого тестирования или автоматизации разработки можно написать логику на UnigineScript. UnigineScript API обладает только базовой функциональностью и ограниченной сферой применения, но доступен для любого проекта на UNIGINE, включая проекты на .NET 5.
Есть два способа добавить скриптовую логику в проект:
- Создав скрипт мира:
1. Создайте ассет скрипта .usc.
2. Определите в нем логику. При необходимости добавьте проверку, загружен ли редактор:
3. Выделите текущий мир и укажите для него сценарий мира. Нажмите Apply и перезагрузите мир.
4. Проверьте окно консоли на наличие ошибок.
После этого логика скрипта будет выполняться как в редакторе, так и в приложении.
- Используя WorldExpression. С той же целью можно использовать ноду WorldExpression, выполняющую логику при добавлении в мир:
1. Нажмите Create -> Logic -> Expression и поместите новую ноду WorldExpression в мир.
2. Напишите логику на UnigineScript в поле Source:
3. Проверьте окно Console на наличие ошибок.
4. Логика будет выполнена немедленно.
Триггеры
Помимо обнаружения столкновений, компонент Collider в Unity может быть использован как триггер, который срабатывает, когда другой коллайдер попадает в его объем.
В UNIGINE Trigger — это специальный тип нод, вызывающих события в определенных ситуациях:
- NodeTrigger вызывает коллбэк при изменении состояния включен/выключен и позиции самой ноды.
- WorldTrigger вызывает коллбэк, когда какая-либо нода (независимо от типа) попадает внутрь или за его пределы.
- PhysicalTrigger вызывает коллбэк, когда физические объекты попадают внутрь или наружу его пределов.
Важно! PhysicalTrigger не обрабатывает столкновения, для этого физические тела и сочленения предоставляют свои собственные события.
WorldTrigger — наиболее распространенный тип триггера, который можно использовать в игровой логике:
Обработка ввода
Обычный игровой ввод Unity:
UNIGINE:
Также можно использовать синглтон ControlsApp для обработки привязок элементов управления к состояниям. Чтобы настроить привязки, откройте настройки Controls:
Рейкастинг
Для обнаружения пересечений лучей с объектами в Unity используется Physics.Raycast. GameObject должен иметь прикрепленный компонент Collider для участия в рейкастинге:
В UNIGINE то же самое делается с помощью Intersections:
* * *
Напоминаем, что получить доступ к бесплатной версии UNIGINE 2 Community можно заполнив форму на нашем сайте.
Все комплектации UNIGINE:
- Community — базовая версия для любителей и независимых разработчиков. Достаточна для разработки видеоигр большинства популярных жанров (включая VR).
- Engineering — расширенная, специализированная версия. Включает множество заготовок для инженерных задач.
- Sim — максимальная версия платформы под масштабные проекты (размеров планеты и даже больше) с готовыми механизмами симуляции.