Русский
Русский
English
Статистика
Реклама

Как собрать паука в Godot, Unigine или PlayCanvas

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




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



Godot


Здесь у меня уже был готов небольшой проект с машинками и паука я решил добавить в одну из сцен (префабов), содержащую в себе подкласс машинок, которые не имеют колёс.
Сама сцена specific_base устроена таким образом, что в основе узел-пустышка, который просто висит где-то в мире, без движения, а по миру перемещается kinematic body внутри него. Камера находится внутри сцены, но вне body, просто следуя за ним.



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



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


Код внутри редактора Godot

Пишем код. Я использую GDScript, потому как особого смысла писать именно на C# в Годо не вижу (не настолько фанат фигурных скобочек):

extends Spatialexport var distance = 2.5#максимальная дистанция, после которой случится перерасчётexport var step = 1#переменная для дополнительного смещения лап (вещь необязательная)#ссылки на центр паука и одну из позиций лап, а также элементы для их храненияexport (NodePath) var spidercenter = nullvar trg_centerexport (NodePath) var spiderleg = nullvar trg_leg#переменные для расстояний по осям x и zvar x_dis = 0.0var z_dis = 0.0#переменная-таймер, а также флагvar time_lag = -1.0# инициализацияfunc _ready():self.hide()#скрыть лапуtrg_center = get_node(spidercenter)#запомнить объектыtrg_leg = get_node(spiderleg)LegPlace()#один раз вызвать установку лапки на позицию# основной циклfunc _process(delta):        #развернуть лапу в направлении центра паука. можно ввести таймер, чтобы делать это через малые интервалыself.look_at(trg_center.global_transform.origin, Vector3(0,1,0))        #включить видимость, если лапа была невидимой. это делалось для того, чтобы показывать её снова, после того как она скрывается в момент перестановки (чтобы перестановка выглядела как появление лапы в новой позиции уже развёрнутой в нужную сторону, а не перенесением с последующим разворачиванием). на самом деле можно было вынести внеочередной разворот и последующий показ лапы в LegPlaceif self.visible == false: self.show()if time_lag>=0:#если флаг-таймер запущен, то наращивать его значениеtime_lag +=1*delta if time_lag>0.06:#при истечении задержки сбросить флаг и вызвать перерисовкуtime_lag = -1.0LegPlace()else:#пока флаг неактивен считать дистанции от лапы до позиции лапы по двум осямx_dis = abs(trg_leg.global_transform.origin.x - self.global_transform.origin.x)z_dis = abs(trg_leg.global_transform.origin.z - self.global_transform.origin.z)if (x_dis + z_dis) > distance:#если дистанция больше лимита, запустить флагtime_lag = 0.0passfunc LegPlace():#собственно, сама функция перестановки лапыself.hide()step = step*(-1)self.global_transform.origin = trg_leg.global_transform.origin+Vector3(0,0,0.5*step)



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



Unigine


После того, как была готова реализация для Godot, я решил перенести это решение и в Unigine engine. Там у меня тоже имелся проект с машинками, правда чтобы не перегружать его я сделал отдельный паучий форк, чтобы впоследствии, наверное, вовсе убрать из него колёса и развивать как-то отдельно.



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



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


Unigine для редактирования кода запускает внешнюю среду

Код:

using System;//стандартная "шапка"using System.Collections;using System.Collections.Generic;using Unigine;//уникальный идентификатор компонента, генерируемый при создании скрипта[Component(PropertyGuid = "5a8dd6f85781adf7567432eae578c5414581ddac")]public class theLegBehavior : Component{[ShowInEditor][Parameter(Tooltip = "CenterSpider")]//указатель на центр паукаprivate Node spiderCenter = null;[ShowInEditor][Parameter(Tooltip = "Target Leg Point")]//указатель на точку крепленияprivate Node legPoint = null;//переменные для вычислений дистанций по осямprivate float x_dis= 0.0f;private float z_dis= 0.0f;private float ifps;//переменная для дельтатаймprivate float time_lag = -1.0f;//таймер-флагprivate void Init()//инициализация{node.Enabled = false;//скрыть лапуLegPlace();//вызвать перестановку лапы}private void Update()//основной цикл{ifps = Game.IFps;//сохранить дельтатаймif (time_lag>=0.0f){//далее уже знакомая конструкцияtime_lag += 1.0f*ifps;if (time_lag>=0.6f) {time_lag = -1.0f;LegPlace();}}else{x_dis = MathLib.Abs(legPoint.WorldPosition.x - node.WorldPosition.x);z_dis = MathLib.Abs(legPoint.WorldPosition.z - node.WorldPosition.z);            if (x_dis + z_dis > 0.8f){time_lag = 0.0f;}}}        //функция перерасчёта положения лапы. здесь уже финальный показ лапы встроен внутрь функции. также тут происходит единичный разворот в сторону центра паука. а постоянный разворот считается вне этого скрипта, а в отдельном, наброшенном на лапу скрипте, хотя я по сути уже это вынес оттуда и можно включить в Update этого скрипта.private void LegPlace(){node.Enabled = false;vec3 targetDirection = vec3.ZERO;targetDirection = (legPoint.WorldPosition - node.WorldPosition);quat targetRot = new quat(MathLib.LookAt(vec3.ZERO, targetDirection, vec3.UP, MathLib.AXIS.Y));quat delta = MathLib.Inverse(targetRot);delta.z = 0;delta.Normalize();node.WorldPosition = legPoint.WorldPosition;        targetDirection = (spiderCenter.WorldPosition - node.WorldPosition);node.SetWorldDirection(targetDirection, vec3.UP, MathLib.AXIS.Y);node.Enabled = true;}}



Видеонарезка паучьего теста в Unigine



PlayCanvas


PlayCanvas игровой движок под webGL, использующий javascript. Недавно начал в нём разбираться. Напоминает нечто среднее между Unity и Godot, но с разработкой онлайн редактор открывается в браузере.

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

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



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



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


В playcanvas редактор кода запускается вновой вкладке браузера

Код:
var TheLegBehavior = pc.createScript('theLegBehavior');//ссылка на центр паукаTheLegBehavior.attributes.add('N_spiderCenter', { type: 'entity' });//ссылка на точку постановки этой лапкиTheLegBehavior.attributes.add('N_legPoint', { type: 'entity' });this.x_dis = 0.0;this.z_dis = 0.0;this.time_lag = -1.0;// initialize code called once per entityTheLegBehavior.prototype.initialize = function() {        };// update code called every frameTheLegBehavior.prototype.update = function(dt) {    if (this.N_spiderCenter) {        this.entity.lookAt(this.N_spiderCenter.getPosition());    }};// постапдейтTheLegBehavior.prototype.postUpdate = function(dt) {    //    if (this.N_spiderCenter) {//        this.entity.lookAt(this.N_spiderCenter.getPosition());//    }    if (time_lag>=0.0){        time_lag+=1.0*dt;        if (time_lag>=0.06){            time_lag=-1.0;            this.LegUpdate();        }            } else {                x_dis = Math.abs(this.entity.getPosition().x-this.N_legPoint.getPosition().x);        z_dis = Math.abs(this.entity.getPosition().z-this.N_legPoint.getPosition().z);                if ((x_dis+z_dis)>3.0){         time_lag=0.0;        }                    }};TheLegBehavior.prototype.LegUpdate = function() {        if (this.N_legPoint) {        this.entity.setPosition(this.N_legPoint.getPosition());    }    //    if (this.N_spiderCenter.enabled === false) {//        this.entity.enabled = false;//    }//    if (this.N_spiderCenter.enabled === true) {//        this.entity.enabled = true;//    }    };


В целом, пока получилась заготовка паучка с четырьмя лапками и не совсем оптимальными расчётами.

Потестить получившегося на текущий момент кадавра можно здесь:
https://playcanv.as/p/rOebDLem/

Я лично пробовал запускать на не слишком мощном смартфоне через Chrome и Dolphin, графика становится похожей на PsOne и вычисления для некоторых лап не работают, пока на экране виден уровень, у края карты лапы проявляются. На слабом ноутбуке наблюдались очень сильные тормоза в Chrome, но в Firefox всё катается нормально. На ноутбуке с дискретной видеокартой и на стационарнике летает в обоих этих браузерах.

На ПК, в отличие от смартфонов в этой демке работает прыжок (по кнопке пробел), заготовка стрейфа (Q и E) и перезагрузка уровня (на R).

Итог



Как видите, языки и движки разные, но тем не менее многие вещи в семействе скриптовых языков делаются довольно похожим образом. А как часто вы осваивали новые для себя игровые движки и фреймворки, с какими основными трудностями столкнулись?
Источник: habr.com
К списку статей
Опубликовано: 04.01.2021 22:21:38
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Программирование

Разработка игр

Webgl

Прототипирование

Godot

Godotengine

Gdscript

Unigine

C

Playcanvas

Javascript

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru