Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Регистрируясь, я даю согласие на обработку данных и условия почтовых рассылок.
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Играйте в Длинные и Короткие нарды онлайн! Наслаждайтесь классической настольной игрой с простыми правилами и захватывающей стратегией. Бросайте кубики, перемещайте шашки и обыгрывайте своего соперника. Играйте прямо сейчас бесплатно!

Нарды Длинные и Короткие онлайн

Настольные, Для двоих, Пошаговая

Играть

Топ прошлой недели

  • cristall75 cristall75 6 постов
  • 1506DyDyKa 1506DyDyKa 2 поста
  • Animalrescueed Animalrescueed 35 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая «Подписаться», я даю согласие на обработку данных и условия почтовых рассылок.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
0 просмотренных постов скрыто
8
Olek.Olegovich
Olek.Olegovich
Лига Разработчиков Видеоигр
Серия RPG Maker

RPG Maker - критика статей⁠⁠

4 месяца назад

Мои посты по разработке на RPG Maker набирают примерно столько же минусов, сколько и плюсов. Приглашаю всех поделиться критикой моих публикаций. Хочу повысить качество контента!

[моё] Посты на Пикабу Минусы RPG Maker Rpg maker mv Статья Плагин Gamedev Урок Обучение Гайд Вопрос Спроси Пикабу Короткопост Текст
4
5
Olek.Olegovich
Olek.Olegovich
Лига Разработчиков Видеоигр
Серия RPG Maker

RPG Maker MV/MZ - Как можно в переменную взять игровое время (время, проведённое в игре) с последнего сохранения?⁠⁠

4 месяца назад

Это можно сделать с помощью команды Выполнить скрипт в событии. Ниже скрипт для MZ с комментариями.

// Для красоты вынес перевод строки времени в кол-во секунд в отдельную функцию.

function convertStringToSeconds(time) {

const array = time.split(":");

return (parseInt(array[0], 10) * 60 * 60) + (parseInt(array[1], 10) * 60) + parseInt(array[2], 10)

}

// Устанавливаем номер переменной, в которую хотим записать значение.

const varId = 1;

// Фиксируем текущее игровое время.

const currentSeconds = $gameSystem.playtime();

// Проверяем, есть ли сохранения.

if (!DataManager.isAnySavefileExists()) {

$gameVariables.setValue(varId, currentSeconds);

} else {

// Определяем индекс последнего сохранения.

const lastSaveFileId = DataManager.latestSavefileId();

// Получаем данные об этом сохранении (нам даже не нужно грузить всё сохранение).

const saveInfo = DataManager._globalInfo[lastSaveFileId];

// Вычисляем, сколько секунд игры было в последнем сохранении.

const lastSeconds = convertStringToSeconds(saveInfo.playtime);

// Вычисляем разницу.

const deltaSeconds = currentSeconds - lastSeconds;

// Записываем в переменную.

$gameVariables.setValue(varId, deltaSeconds);

}

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

Версия для MV:

function convertStringToSeconds(time) { const array = time.split(":"); return (parseInt(array[0], 10) * 60 * 60) + (parseInt(array[1], 10) * 60) + parseInt(array[2], 10) }

const varId = 1; const currentSeconds = $gameSystem.playtime();

if (!DataManager.isAnySavefileExists()) { $gameVariables.setValue(varId, currentSeconds); }

else {

const lastSaveFileId = DataManager.latestSavefileId();

const saveInfo = DataManager.loadGlobalInfo()[lastSaveFileId];

const lastSeconds = convertStringToSeconds(saveInfo.playtime);

const deltaSeconds = currentSeconds - lastSeconds;

$gameVariables.setValue(varId, deltaSeconds);

}

Если нужны какие-то данные, которых нет в информации о сохранении, придётся грузить файл сохранения. Это можно сделать так:

// Устанавливаем номер переменной, в которую хотим записать значение.

const varId = 1;

// Проверяем, есть ли сохранения.

if (!DataManager.isAnySavefileExists()) {

$gameVariables.setValue(varId, 0);

} else {

// Определяем индекс последнего сохранения.

const lastSaveFileId = DataManager.latestSavefileId();

// Получаем имя файла этого сохранения.

const saveName = DataManager.makeSavename(lastSaveFileId);

// Загружаем данные из файла.

StorageManager.loadObject(saveName).then(contents => {

// Данные в contents. Обрабатываем их, как нужно.

return 0;

});

}

На смежные и схожие вопросы могу ответить в этом треде.

Показать полностью
[моё] Разработка Gamedev Программирование Javascript RPG Maker Rpg maker mv Плагин Текст Урок Статья Обучение Гайд
0
3
Olek.Olegovich
Olek.Olegovich
Лига Разработчиков Видеоигр
Серия RPG Maker

RPG Maker MV/MZ - Добавление языковых локализаций в завершённый проект⁠⁠

4 месяца назад

Вступление

Я разработал плагин для языковых локализаций, здесь описание поподробнее. Постепенно буду добавлять в него функционал. Если вам нужна какая-то конкретная функция, напишите идею в теме плагина. Также обращу внимание, что в плагине есть функционал по экспорту языковых данных в Excel-таблицу и импорту из неё.

Важный совет. Если вы допускаете, что в вашей игре будет более одного языка (возможно, не сразу, но в будущем), лучше сразу разрабатывать с учётом локализаций. То есть нигде в редакторе не используйте захардкоженный текст, только теги из файлов локализации. Сначала можно прописать только один язык, потом по надобности добавлять другие. Тогда вам не придётся мучаться с экспортом текста из игры.

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

Как-то раз я выполнил такой заказ для игры на RPG Maker MV. Вероятно, решение прокатит и на MZ. Если не сработает, напишите в этой теме.

Задача

  1. Экспортировать текст из игры в JSON.

  2. Сконвертировать JSON в XLSX и отправить получившуюся таблицу переводчику.

  3. Дождаться готового перевода в XLSX формате.

  4. Конвертировать новую таблицу в JSON и внедрить новый язык в проект.

Формат JSON поддерживает произвольную структуру данных. Объекты, массивы, любой уровень вложенности. При этом переводчик с JSON работать не хотел, нужно было ему обеспечить таблицу. Поэтому я решил для хранения данных локализации использовать один JSON-файл с плоским объектом. То есть был только один объект в корне файла, и каждое его свойство было текстовым. Никаких вложенных объектов.

Инструкция

  • Сначала нужно экспортировать текст из проекта. Я написал скрипт, который находит все диалоги (команда "Показать сообщение"), извлекает из них текст и сразу генерирует JSON-файл с нужной структурой. Вот он.

  • Этот скрипт написан на JS. Чтобы его исполнить, можно установить Node.js и запустить скрипт командой node export-localization.js

  • Можно также переписать скрипт на python, bash или другой язык и исполнить удобными вам инструментами. В принципе, скрипт несложный (даже примитивный).

  • В результате мы получим файл с таким содержимым:

{

"<тег>": "<реплика>"

}

  • Теперь забиваем в поисковик: "json to xlsx". Берём любой понравившийся сервис. Например, этот.

  • Скорее всего, мы получим таблицу с 2 строками и большим количеством столбцов. Переводчику будет неудобно работать с такой. Он ожидает 2 столбца: в одном теги, в другой - текст, который нужно перевести (переводчик либо будет редактировать этот столбец, либо добавит новый).

  • Если у вас получилось так, то просто транспонируйте получившуюся таблицу. Это можно сделать и в Esxcel, и в LibreOffice, и в Google Sheets. Не знаете, как? Поищите в интернете, это несложно (конкретная кнопка зависит от инструмента, поэтому тут не пишу, но она точно есть).

  • Отправляем таблицу переводчику, ждём перевода.

  • Теперь новый XLSX нужно конвертировать в JSON. Сначала транспонируем таблицу, чтобы у нас было 2 строки и множество столбцов.

  • Вбиваем в поисковик: "xlsx to json". Опять берём любой подходящий сервис, вроде этого. Конвертируем, получаем новый json-файл.

  • Переименовываем новый JSON-файл, как нам нужно ("en.json", "ru.json" и т.д.).

  • Вставляем в проект, добавляем язык в параметры плагина локализации (здесь конкретные действия зависят от используемого плагина).

Заключение

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

Самое ценное в этой статье - скрипт на экспорт текста, обратите на него внимание. У DK есть инструмент, который извлекает весь текст из игры, но он не генерирует JSON-файл с нужной структурой и уникальными тегами (очень важно, чтобы теги были уникальными).

Надеюсь, мне удалось достаточно раскрыть тему, остались ли вопросы?

Показать полностью
[моё] Разработка Gamedev Программирование Javascript RPG Maker Плагин Текст Урок Статья Обучение Гайд Rpg maker mv
0
3
Olek.Olegovich
Olek.Olegovich
Лига Разработчиков Видеоигр
Серия RPG Maker

RPG Maker MV/MZ - Обработка нажатий на клавиатуру и мышь⁠⁠

4 месяца назад

Предисловие

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

Существует несколько способов это делать.

Способ 0

Возможно, вам достаточно будет назначить стандартные действие на нестандартные клавиши. Например, сделать ходьбу по WASD. Для подобного достаточно расширить словарь Input.keyMapper, об этом подробнее в другом гайде.

Способ 1

Небольшая справка: событие - это сообщение, которое возникает при выполнении определённых условий. Например, если пользователь пошевелил мышь или тыкнул по клавише - в системе происходит соответствующее событие.

С помощью функции document.addEventListener(<событие, <функция>) можно назначить функции-обработчики на различные события.

Можно обрабатывать нажатие на клавишу:

document.addEventListener("keydown", keyDownHandler);

function keyDownHandler(event) {

if (Input.keyMapper[event.keyCode] == "ok") {

// Ваш код

}

};

"keydown" - это название события нажатия на клавишу клавиатуры. Внутри функции обработчика мы проверяем, не помечена ли нажатая клавиша, как "ok" в Input.keyMapper.

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

document.addEventListener("keydown", keyDownHandler);

function keyDownHandler(event) {

// 70 - это код клавиши F

if (event.keyCode == 70) {

// Ваш код

}

};

Существуют различные события, которые можно обрабатывать в играх. Вот некоторые:

// Нажатие на клавишу клавиатуры:

document.addEventListener("keydown", keyDownHandler);

// Нажатие на клавишу мыши:

document.addEventListener("click", mouseClickHandler);

// Двойное нажатие на клавишу мыши:

document.addEventListener("dblclick", mouseDoubleClickHandler);

// Игрок пошевелил мышкой:

document.addEventListener("mousemove", keyDownHandler);

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

document.body.addEventListener("mousedown", event => {

if (event.button == 0) {

// Нажата левая кнопка

}

else if (event.button == 2) {

// Правая кнопка

}

else {

// Другая кнопка

}

}

Способ 2

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

Во-первых, в rmmz_core.js можно найти функции, которые делают примерно то, о чём я писал выше:

TouchInput._setupEventHandlers = function() {

const pf = { passive: false };

document.addEventListener("mousedown", this._onMouseDown.bind(this));

document.addEventListener("mousemove", this._onMouseMove.bind(this));

document.addEventListener("mouseup", this._onMouseUp.bind(this));

document.addEventListener("wheel", this._onWheel.bind(this), pf);

document.addEventListener("touchstart", this._onTouchStart.bind(this), pf);

document.addEventListener("touchmove", this._onTouchMove.bind(this), pf);

document.addEventListener("touchend", this._onTouchEnd.bind(this));

document.addEventListener("touchcancel", this._onTouchCancel.bind(this));

window.addEventListener("blur", this._onLostFocus.bind(this));

};

TouchInput._onMouseDown = function(event) {

if (event.button === 0) {

this._onLeftButtonDown(event);

} else if (event.button === 1) {

this._onMiddleButtonDown(event);

} else if (event.button === 2) {

this._onRightButtonDown(event);

}

};

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

const Origin_TouchInput_onCancel = TouchInput._onCancel;

TouchInput._onCancel = function(x, y) {

// Ваш код

Origin_TouchInput_onCancel.apply(this, [x, y])

};

Сначала вы выполняем код, после (что важно!) вызываем оригинальный метод. Можно ваш код выполнять после кода движка. Но обязательно вызывайте Origin_TouchInput_onCancel, иначе стандартная обработка нажатия движком не выполнится.

Ещё момент. Напрямую это не относится к тему, но может быть полезно.

$gameTemp.reserveCommonEvent(N);

С помощью этой функции можно вызвать общее событие. N - номер события в Базе данных проекта. К примеру, вы можете по нажатию на какую-то клавишу вызывать общее событие, где и описана ваша уникальная игровая логика.

Вот здесь демо-проект с реализацией такой идеи.

После запуска новой игры попробуйте нажать на F и ПКМ мыши.

Буду дополнять этот гайд по необходимости, пишите ваши предложения и замечания.

Каталог моих бесплатных плагинов для RPG Maker

Показать полностью
[моё] Разработка Gamedev Программирование Javascript RPG Maker Rpg maker mv Плагин Текст Урок Статья Обучение Гайд Длиннопост
0
9
Olek.Olegovich
Olek.Olegovich
Лига Разработчиков Видеоигр
Серия RPG Maker

RPG Maker MV/MZ - Управление по WASD⁠⁠

4 месяца назад

Добавить поддержку клавиш W, A, S, D клавиатуры легко в MV и MZ.

Для этого достаточно добавить в проект такой код:

(function () {

var replacedKeyMapper = {

87: 'up',

65: 'left',

83: 'down',

68: 'right',

69: 'pagedown',

};

for (code in replacedKeyMapper) {

Input.keyMapper[code] = replacedKeyMapper[code];

}

})();

Здесь мы также "перекинули" стандартный функционал клавиши W на E.

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

У каждой клавиши есть числовой код. Представим, что в движке они помечаются маркерами. Например, стрелка вверх помечена маркером 'up'. Если игрок нажимает на эту стрелку, движок видит срабатывание маркера 'up' и обрабатывает это событие.

Маркеры задаются через словарь. Эта структура данных состоит из пар ключ-значение. Здесь ключ - числовой код клавиши, а значение - маркер. Все ключи уникальные, они не могут повторятся. Значения - могут.

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

При желании, вы можете добавлять свои пары ключ-значение в объект replacedKeyMapper из кода выше.

Вот код из файла движка rmmz_core.js:

Input.keyMapper = {

9: "tab", // tab

13: "ok", // enter

16: "shift", // shift

17: "control", // control

18: "control", // alt

27: "escape", // escape

32: "ok", // space

33: "pageup", // pageup

34: "pagedown", // pagedown

37: "left", // left arrow

38: "up", // up arrow

39: "right", // right arrow

40: "down", // down arrow

45: "escape", // insert

81: "pageup", // Q

87: "pagedown", // W

88: "escape", // X

90: "ok", // Z

96: "escape", // numpad 0

98: "down", // numpad 2

100: "left", // numpad 4

102: "right", // numpad 6

104: "up", // numpad 8

120: "debug" // F9

};

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

Есть аналогичный словарь для геймпада:

Input.gamepadMapper = {

0: "ok", // A

1: "cancel", // B

2: "shift", // X

3: "menu", // Y

4: "pageup", // LB

5: "pagedown", // RB

12: "up", // D-pad up

13: "down", // D-pad down

14: "left", // D-pad left

15: "right" // D-pad right

};

Можно также создать обработчик нажатий на клавиатуру и там смотреть на непосредственно код нажатой клавиши. Полезно, если у движка нет подходящего стандартного маркера. Но это уже для продвинутых пользователей ;) Пишите, если нужен гайд по этому.

Коды клавиш легко находятся в интернете. Можно смотреть их, к примеру, тут. Нужны DEC-коды (то есть десятичные).

Ещё важный совет. Не меняйте код движка, не редактируйте стандартные файлы. Мало того, что это запрещено правообладателем, это также неудобно и небезопасно. Что, если вы ошибётесь или захотите откатить изменения? JavaScript позволяет переопределять всё, что удобно. Поэтому для изменения кода движка используйте плагины.

Пишите ваши вопросы в этом треде, если остались.

Каталог моих бесплатных плагинов для RPG Maker

Показать полностью
[моё] Разработка Gamedev Программирование Javascript RPG Maker Rpg maker mv Плагин Текст Урок Статья Обучение Гайд
2
3
8bitsage
8bitsage

Unreal Engine 5 и VR с нуля. Часть 12. Передвижение персонажа в VR (locomotion system)⁠⁠

5 месяцев назад

Введение

Видя как передвигается персонаж в таких играх как Blade And Sorcery, BoneWorks, Battle Talent, Contractors, хотелось разобраться, как и какие варианты реализации locomotion system можно реализовать в VR? Видеоуроки направленные конкретно для VR, не раскрывают как подробно реализовать продвинутое передвижение персонажа, какие сложности есть в этом.

Однажды, один пользователь на форуме unreal engine сказал примерно такие слова: "нет разницы VR это или игра от третьего лица или от первого лица, большинство механик реализуются одинаково. Разница лишь в восприятии функционала и небольших особенностях реализации." В целом, я согласен. что так оно и есть, абсолютно все механики можно адаптировать под VR, поэтому я решил адаптировать Locomotion System из проекта Lyra Unreal Engine.

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

Так же никто не запрещает взять проект ALS или GameAnimationSample от Unreal Engine (но с нуля там сложно разобраться будет).

Небольшая предыстория в коротком видео: https://www.youtube.com/shorts/phE0y7TSpLE

Уроки по воссозданию Locomotion system из проекта Lyra

Из того что я нашел полезным, могу выделить два плейлиста на ютубе. Всю логику расчетов я переносил в С++.

1. Канал Outcast DevSchool имеет плейлист как с нуля воссоздать передвижение персонажа из Lyra, но он использует свой пак анимаций, который расширяет вариативность движения бедер в разных направлениях.

https://www.youtube.com/playlist?list=PL8-kndpxmv9gBoGznFqJo...

2. Канал Unreal Shinobi имеет похожий плейлист, использует бесплатные анимации из проекта Lyra. Но в нем было излишество для меня, автор тутора использует GamePlayTag для обозначения состояний передвижения игрока, вещь полезная но в моем случае была излишняя.

https://www.youtube.com/playlist?list=PL25BRJmUKoa-UKrMACwoG...

Я смотрел оба плейлиста и взял все подходящее для моего проекта.

Стоит обратить внимание на эти каналы:

LocoDev - имеет интересные туториалы по передвижению https://www.youtube.com/@LocoDev

Quinn Kuslich - Advanced Thumbstick Locomotion Tutorial конкретно на VR примере (хочется перенести отсюда VFX для телепорта) https://www.youtube.com/watch?v=KTPx8PeKyQM&t=2030s&ab_channel=QuinnKuslich

Отличия реализации системы передвижения от туторов для VR

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

1. Используем направление камеры, а не Actor Location/Rotation. В VR в основном используют направление камеры для движения персонажа вперед. Это значит, что если ты нажал стик бежать вперед, то куда смотрит камера, туда и будем бежать. В VR камера HMD и капсула должны быть синхронизированы 1 к 1 (об этом вы должны позаботиться чтобы не было рассинхронизации). https://www.youtube.com/shorts/l9l_Nl8uBB4

2. При использовании Orientation Warping (коротко о Orientation Warping), учитываем оба случая - Движение на стик и движение физически от камеры. https://www.youtube.com/shorts/tX__fngNLZA

3. При использовании Stride Warping учитываем скорость при движении от стика и скорость получаемую от физического движения HMD (когда ходим по комнате). https://www.youtube.com/shorts/CxPJ3lQ03-w

Stride Warping позволяет динамически изменять длину шага, потому что анимации бега обычно рассчитаны на скорость 400 см/с, а для анимаций шага 200 см/с. Физический же шаг может быть индивидуальным 40-160 см/с. Демонстрация работы Stride Warping при физическом передвижении по комнате: https://www.youtube.com/shorts/Pxmgqdd03No

4. Используем Dead Blending Node, вместо INERTIALIZATION Node. Я столкнулся с проблемой, что при резкой смене анимации, происходил прыжок ошибочной позы в 1 кадр и это отстреливало в IK верхней части тела. Подробнее о проблеме в видео - https://www.youtube.com/shorts/QGK9naoeV0A

Заключение

Надеюсь эта информация тебе поможет построить свою систему передвижения, под потребности проекта.

Телеграм канал Unreal Engine VR
Поддержать канал

Показать полностью
[моё] Unreal Engine Гайд Gamedev Разработка Инди Текст
0
3
8bitsage
8bitsage

Как конвертировать Blueprint в С++ с помощью Node to Code в Unreal Engine⁠⁠

5 месяцев назад

Введение

Изучая VR Expansion Plugin, я столкнулся с тем, что реализация самой Grab System написана в блюпринте персонажа в отдельных функциях, а так как у меня проект на С++ я решил просто переписать этот код на С++. Так как функций около 35 и они довольно объемные по коду, я решил поискать способ как ускорить конвертацию блюпринт кода на С++, поэтому расскажу сегодня про плагин Node to Code.

Где скачать Node to Code?

Сам репозиторий плагина находится здесь https://github.com/protospatial/NodeToCode?tab=readme-ov-file

Плагин поддерживает версии UE 5.3-5.5 скачиваем бинарник для своей версии UE - https://github.com/protospatial/NodeToCode/releases/tag/v1.2.3

Как работает плагин?

Анализ Blueprint: фиксирует всю структуру графа Blueprint, включая потоки выполнения, соединения данных, ссылки на переменные и комментарии.

  • Несколько вариантов LLM: используйте облачные провайдеры (OpenAI, Anthropic Claude, Google Gemini, DeepSeek) или запускайте полностью локально через Ollama для полной конфиденциальности.

  • Эффективная сериализация: преобразует блюпринт чертежи в специальную схему JSON, которая сокращает использование токенов на 60–90 % по сравнению с подробным текстовым форматом чертежей UE.

  • Интегрированный редактор: просматривайте переводы в закрепляемом окне редактора Unreal с подсветкой синтаксиса, примечаниями по реализации и темами

Как пользоваться плагином?

1. Качаем плагин 2. Добываем Api ключ LLM OpenAI, Anthropic Claude, Google Gemini, DeepSeek) 3. Заходим в Project Settings>Plugins>NodeToCode> вставляем Api ключ 4. Настраиваем глубину конвертации блюпринта в С++.

Я использую глубину =1 (это значит переписать то что видно в графе блюпринта и описать функции с параметрами которые вызываются, но без их внутренней реализации).

Плагин ускорил перенос BP в С++, код требует правок, но 80% работы он выполняет отлично.

Краткий обзор от меня в коротком shorts - https://youtube.com/shorts/QJTYkJHtg74?si=5inyYPte2GyveR_Y

Телеграм канал Unreal Engine VR
🤝 Поддержать канал

Показать полностью
[моё] Unreal Engine Gamedev Разработка Гайд Blueprint Текст
0
5
8bitsage
8bitsage

Unreal Engine 5 и VR с нуля. Часть 11. Естественный спринт в VR: Управление скоростью с помощью махов рук. Arm Swinging спринт⁠⁠

6 месяцев назад

Введение

В феврале, я проходил курс по С++ для Unreal Engine в контексте VR. В это же время я начал параллельно писать основу для VR проекта с нуля, но в какой то момент, понял насколько много вещей нужно учесть и протестировать, прежде чем двигаться дальше.

Я закомментировал весь написанный код и перешел на VR Expansion Plugin. В этом плагине уже решено множество проблем, как синхронизация камеры HMD и капсулы персонажа, поведение капсулы когда ты движешься физически упираешься в стену и так далее. Я до сих пор разбираю код этого плагина. Плагин поддерживает разные версии Unreal Engine. Всё доступно в репозитории бесплатно: https://github.com/mordentral/VRExpansionPlugin

Я полностью перенес код VR Expansion Plugin в свой проект, чтобы в последующем модифицировать его. Так как я базируюсь на коде этого плагина, я не буду описывать туториалы "как с нуля построить VR проект", вроде бы звучит логичным "покажи как перенести код из VR Expansion Plugin и модифицировать его", но у меня столько времени нет.

Статьи будут выходить, в статьях я буду стараться передавать модульный функционал. Показывая пример как его можно применить на простом примере. Так как контекст всех проектов разный, основываясь на моем примере вы можете применить его у себя (нейронки в помощь, грузите ей "свой контекст" и "мой пример", смотрите как можно интегрировать и надо ли оно вам вобще)

А сегодня поговорим про перевод персонажа в спринт с помощью махов рук. Такая механика применяется например в Blade and Sorcery или Battle Talent.

Функции вероятнее всего будут приложены скриншотами, а скопировать код можно будет из https://gist.github.com/8bitsage

Код этой статьи: https://gist.github.com/8bitsage/0e17f196d2114ec7d663e08a29204c5b

Концепция механики Arm Swinging

Идея проста: когда игрок двигается вперед и активно машет руками (как при беге), персонаж автоматически переходит в режим спринта. Это позволяет:

  • Освободить кнопки контроллера для других действий.

  • Сделать передвижение более иммерсивным.

  • Связать физическую активность игрока со скоростью персонажа в игре.

Архитектура решения

Шаг 1: Определение переменных

В заголовочном файле (h файл) класса персонажа (например, AVRPlayerCharacter.h) добавляем необходимые переменные:

// === Настраиваемые параметры ===
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement|ArmSwing",
meta = (ClampMin = "3.0", ClampMax = "15.0"))
float ArmSwingThreshold = 7.0f;
// Порог активации спринта в сантиметрах
// Определяет минимальное суммарное расстояние, которое должны пройти
// оба контроллера за один цикл проверки для активации спринта
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement|ArmSwing",
meta = (ClampMin = "0.01", ClampMax = "0.2"))
float CheckFrequency = 0.02f;
// Частота проверки движения контроллеров в секундах
// Меньшее значение = более отзывчивая механика, но больше нагрузка
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float SprintSpeed = 600.0f;
// Скорость персонажа при спринте (см/с)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float RunSpeed = 400.0f;
// Скорость персонажа при беге (см/с)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float WalkSpeed = 200.0f;
// Скорость персонажа при ходьбе (см/с)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement",
meta = (ClampMin = "0.1", ClampMax = "0.5"))
float MinStickMagnitudeForRun = 0.3f;
// Минимальное отклонение стика для перехода от ходьбы к бегу
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement",
meta = (ClampMin = "0.5", ClampMax = "0.9"))
float MinForwardRatioForSprint = 0.7f;
// Минимальная доля движения вперед для возможности спринта
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement",
meta = (ClampMin = "0.3", ClampMax = "0.7"))
float MaxLateralRatioForSprint = 0.5f;
// Максимальная доля бокового движения для возможности спринта
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement",
meta = (ClampMin = "0.1", ClampMax = "1.0"))
float BackwardSpeedMultiplier = 0.7f;
// Множитель скорости при движении назад
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement",
meta = (ClampMin = "0.1", ClampMax = "1.0"))
float SidewaysSpeedMultiplier = 0.8f;
// Множитель скорости при движении вбок
// === Внутренние переменные ===
FVector LastLeftControllerPos;
// Предыдущая позиция левого контроллера для расчета дельты
FVector LastRightControllerPos;
// Предыдущая позиция правого контроллера для расчета дельты
FTimerHandle ArmSwingTimerHandle;
// Хэндл таймера для периодической проверки движения
bool bIsArmSwinging = false;
// Флаг текущего состояния: true если игрок машет руками достаточно интенсивно
void CheckArmSwing();
void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent);
void MoveCharacter(const FInputActionValue& Value);
void HandleMovementInput(const FVector2D& InputValue);

Логика определения скорости:

  1. Слабое отклонение стика (< MinStickMagnitudeForRun) — всегда ходьба, независимо от махов руками

  2. Сильное отклонение стика (≥ MinStickMagnitudeForRun): Движение вперед (ForwardRatio > MinForwardRatioForSprint и боковое отклонение < MaxLateralRatioForSprint):С махами руками → Спринт Без махов руками → Бег Движение назад или вбок → Только бег (спринт невозможен)

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

Ссылки на документацию:

  • UPROPERTY

  • FTimerHandle

  • Meta tags

Шаг 2: Реализация детекции махов руками

В файле реализации (AVRPlayerCharacter.cpp) создаем функцию проверки:

Как это работает:

  1. Функция вызывается каждые CheckFrequency секунд (по умолчанию 0.02с = 50 раз в секунду) Настройте для оптимальной производительности.

  2. Измеряется расстояние, пройденное каждым контроллером с последнего вызова

  3. Если суммарное расстояние превышает ArmSwingThreshold, считается что игрок "бежит"

Шаг 3: Инициализация системы

В методе BeginPlay() запускаем периодическую проверку:

Ссылки на документацию:

  • Timer Management

  • UMotionControllerComponent

Шаг 4: Интеграция с Enhanced Input System

Теперь нужно связать механику с системой ввода. Сначала настраиваем привязку action'а:

Затем реализуем функцию обработки ввода:

Шаг 5: Управление скоростью персонажа

Важно понимать! В моем примере применение скорости персонажа в зависимости от направления взгляда камеры. Например, стик отодвинут вперед (мы бежим вперед), повернули голову на 90 градусов, мы по прежнему бежим вперед, только уже в ту сторону, когда повернулась голова.

Иногда делают реализации, когда вектор движения применяется от направления капсулы. Направление "вперед" для ввода с джойстика определяется направлением "вперед" капсулы персонажа (или его тела), а не тем, куда смотрит HMD (голова). Игрок может свободно осматриваться головой, не меняя направления движения. При этом повороты самой капсулы (тела персонажа) обычно управляются отдельно, например, правым стиком (snap turn/smooth turn) или физическим поворотом игрока, если включено bUseControllerRotationYaw для персонажа и соответствующая логика в PlayerController.

Вернемся к моему примеру. Основная логика применения скорости находится в HandleMovementInput:

Ссылки на документацию:

  • Enhanced Input System

  • UCharacterMovementComponent

  • AddMovementInput

Настройка в редакторе

1. Создание Input Action

  1. Создайте новый Input Action IA_MoveCharacter

  2. Установите Value Type: Axis2D

  3. В Input Mapping Context привяжите к левому стику VR контроллера

  4. Укажите персонажу Input Mapping Context

2. Настройка параметров движения

В Blueprint персонажа или в Details панели вы можете настроить все параметры:Параметры махов руками:

  • Arm Swing Threshold — чувствительность активации спринта (см)

  • Check Frequency — частота проверки движения контроллеров

Скорости движения:

  • Sprint Speed — скорость при спринте

  • Run Speed — скорость при беге

  • Walk Speed — скорость при ходьбе

Пороги направления:

  • Min Stick Magnitude For Run — минимальное отклонение стика для бега

  • Min Forward Ratio For Sprint — доля движения вперед для спринта

  • Max Lateral Ratio For Sprint — максимальная доля бокового движения для спринта

Множители скорости:

  • Backward Speed Multiplier — коэффициент замедления при движении назад (0.7 = 70% от обычной скорости)

  • Sideways Speed Multiplier — коэффициент замедления при движении вбок (0.8 = 80% от обычной скорости)

Демонстрация этой логики на моем проекте:

Rutube: https://rutube.ru/shorts/ced7d33345b2d47e399f9f5f171dcd2e/

Youtube: https://youtube.com/shorts/4NbbaeqUZ7k

Заключение

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

Телеграм канал Unreal Engine VR

Поддержать канал

Показать полностью 5
[моё] Гайд Разработка Unreal Engine Gamedev Виртуальная реальность Oculus Rift Длиннопост
0
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии