Некоторые игры позволяют пользователям изменять состояние внутриигровых объектов, таких как движущиеся объекты для украшения домов в серии Sims. Масштабирование - один из возможных подходов к модификации.

В этой демонстрации можно изменить длину ребра между двумя точками поворота. Система также представлена ​​как связь вершина-ребро графа. Узлы - это объекты поворота, а края - объекты масштабирования.

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

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

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

Узлы, то есть опорные точки

Узлы - это сферы с GraphNode MonoBehaviour, которые можно перемещать с помощью мыши и инструмента перемещения в редакторе. Их изменение преобразования приводит к тому, что края, у которых они являются начальной или конечной точкой, также изменяют свое преобразование.

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

Когда преобразование GameObject изменяется, флаг hasChanged его преобразования устанавливается в значение true. Сброс этого флага, установка его в ложное состояние, оставлены на усмотрение программиста. В этом случае, когда мышь освобождается от игрового объекта, она перестает двигаться, следовательно, никаких изменений в преобразовании в будущем не будет.

Края

Ребра - это игровые объекты, масштабируемые по двум точкам поворота. В своей реализации я использовал кубы в качестве заполнителей, но также можно использовать другие объекты. Однако вам может потребоваться настроить значения.

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

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

Используя разные значения преобразования двух узловых точек, вычисляется преобразование края. Его масштаб линейно зависит от расстояния между узлами. Поскольку край находится между узлами, его положение - это середина их положений. Наконец, с помощью LookRotation вектор вперед игрового объекта устанавливается так, чтобы смотреть в направлении вектора, который начинается от начальной точки и заканчивается в конечной точке. После внесения изменений в масштабирование масштабируемая переменная, для которой установлено значение true, изменение преобразования сигнала завершается обновлением.

Если ребро масштабировано, то наша работа с его родителями закончилась. Если игра протестирована, перемещение узлов осуществляется с помощью инструмента перемещения. Если бы я перемещал узлы с помощью мыши, они могли бы самостоятельно установить флаг hasChanged. Здесь я установил для их флага transform.hasChanged значение false в Update. Масштабированное логическое значение также сбрасывается, так как масштабирование выполнено полностью, а состояние масштабирования перешло в нормальное состояние.

Порядок исполнения

transform.hasChanged должен быть установлен программистом, когда заканчивается изменение преобразования для игрового объекта. Когда установка флага выполняется на одном этапе с модификациями. Состояние гонки приводит к тому, что одно ребро узла обновляется правильно, но другое ребро видит флаг false, и к этому ребру не применяются никакие изменения. С помощью Порядка выполнения функций событий в документах Unity. Я решил внести изменения в FixedUpdate и установить флаг Обновление. таким образом после внесенных изменений устанавливаются флаги.

Редактор против игры

Два способа сброса флага hasChanged приводят к необходимости изменить тип движения с помощью простой переменной enum. Это используется для тестирования разработки, я подумал, что есть несколько важных моментов, поэтому оставил это для проекта. Если состояние - движение мыши, флаги автоматически устанавливаются, когда мышь покидает узел. В противном случае эти узлы перемещаются с помощью инструментов, и в обновлении GraphEdge MonoBehavior устанавливается флаг, если масштабирование завершено.

Вот редактор, тестирующий бесплатную реализацию GraphEdge:

Здесь вы можете видеть, что обновление удалено, поскольку мы больше не устанавливаем флаг transform.hasChanged с края. После удаления переменных TestMode и Scaled. Узлы уже устанавливают этот флаг, когда отпускают мышь.

Также можно добавить среду VR или дополнительные элементы управления для перемещения узлов по оси Z. таким образом можно достичь большего ощущения глубины.

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

Вы можете найти проект здесь.

Удачной настройки!

Первоначально опубликовано на сайте http://sscriptiee.wordpress.com 26 сентября 2019 г.