С unity автоматическое движение по траектории. Как рисовать траекторию траектории с помощью встроенного механизма физики Unity3d

OpenGL (Open Graphics Library - открытая графическая библиотека) - спецификация, определяющая независимый от языка программирования кросс-платформенный программный интерфейс для написания приложений, использующих двумерную и трехмерную компьютерную графику.
Включает более 250-ти функций для рисования сложных трехмерных сцен из простых примитивов. Используется при создании видео-игр, САПР, виртуальной реальности, визуализации в научных исследованиях. Под Windows конкурирует с DirectX.
Спецификация
На базовом уровне, OpenGL - это просто спецификация, то есть документ, описывающий набор функций и их точное поведение. Производители оборудования на основе этой спецификации создают реализации - библиотеки функций, соответствующих набору функций спецификации. Реализация использует возможности оборудования, там где это возможно. Если аппаратура не позволяет реализовать какую-либо возможность, она должна быть эмулирована программно. Производители должны пройти специфические тесты (conformance tests - тесты на соответствие) прежде чем реализация будет классифицирована как OpenGL реализация. Таким образом, разработчикам программного обеспечения достаточно научиться использовать функции, описанные в спецификации, оставив эффективную реализацию последних разработчикам аппаратного обеспечения.
Эффективные реализации OpenGL существуют для Windows, Unix платформ, PlayStation 3 и Mac OS. Эти реализации обычно предоставляются изготовителями видеоадаптеров и активно используют возможности последних. Существуют также чисто программные реализации спецификации OpenGL, одной из которых является библиотека Mesa. Из лицензионных соображений Mesa является «неофициальной» реализацией OpenGL, хотя полностью с ней совместима на уровне кода.
Спецификация OpenGL пересматривается Консорциумом ARB (Architecture Review Board), который был сформирован в 1992 году. Консорциум состоит из компаний, заинтересованных в создании широко распространенного и доступного API. Согласно официальному сайту OpenGL, членами ARB с решающим голосом на ноябрь 2004 года являются производители профессиональных графических аппаратных средств SGI, 3Dlabs, Matrox и Evans & Sutherland (военные приложения), производители потребительских графических аппаратных средств ATI и NVIDIA, производитель процессоров Intel, и изготовители компьютеров и компьютерного оборудования IBM, Apple, Dell, Hewlett-Packard и Sun Microsystems, а также один из лидеров компьютерной игровой индустрии id Software. Microsoft, один из основоположников Консорциума, покинула его в марте 2003 года. Помимо постоянных членов, каждый год приглашается большое количество других компаний, становящихся частью OpenGL ARB в течение одного года. Такое большое число компаний, вовлеченных в разнообразный круг интересов, позволило OpenGL стать прикладным интерфейсом широкого назначения с большим количеством возможностей.
Курт Экелей (Kurt Akeley) и Марк Сегал (Mark Segal) являются авторами оригинальной спецификации OpenGL. Крис Фрэзиер (Chris Frazier) редактировал версию 1.1. Йон Лич (Jon Leech) редактировал версии с 1.2 по настоящую версию 2.0.
Архитектура
OpenGL ориентируется на следующие две задачи:
скрыть сложности адаптации различных 3D-ускорителей предоставляя разработчику единый API
скрыть различия в возможностях аппаратных платформ, требуя имплементации недостающей функциональности с помощью софтверной эмуляции
Основным принципом работы OpenGL является получение наборов векторных графических примитивов в виде точек, линий и многоугольников с последующей математической обработкой полученных данных и построением растровой картинки на экране и/или в памяти. Векторные транформации и растеризация выполняются графическим конвейером (graphics pipeline), который по сути представляет из себя дискретный автомат. Абсолютное большинство команд OpenGL попадают в одну из двух групп: либо они добавляют графические примитивы на вход в конвейер, либо конфигурируют конвейер на различное исполнение транформаций.
OpenGL является низкоуровневым, процедурным API, что вынуждает программиста диктовать точную последовательность шагов, чтобы построить результирующую растровую графику (императивный подход). Это является основным отличием от дескрипторных подходов, когда вся сцена передается в виде структуры данных (чаще всего дерева), которое обрабатывается и строится на экране. С одной стороны императивный подход требует от программиста глубокого знания законов трёхмерной графики и математических моделей, с другой стороны даёт свободу внедрения различных инноваций.
Расширения
Стандарт OpenGL, с появлением новых технологий, позволяет отдельным производителям добавлять в библиотеку функциональность через механизм расширений. Расширения распространяются с помощью двух составляющих: заголовочный файл, в котором находятся прототипы новых функций и констант, а также драйвер устройства, поставляемого разработчиком. Каждый производитель имеет аббревиатуру, которая используется при именовании его новых функций и констант. Например, компания NVIDIA имеет аббревиатуру NV, которая используется при именовании ее новых функций, как, например, glCombinerParameterfvNV(), а также констант, GL_NORMAL_MAP_NV. Может случиться так, что определенное расширение могут реализовать несколько производителей. В этом случае используется аббревиатура EXT, например, glDeleteRenderbuffersEXT. В случае же, когда расширение одобряется Консорциумом ARB, оно приобретает аббревиатуру ARB и становится стандартным расширением. Обычно, расширения, одобренные Консорциумом ARB включаются в одну из последующих спецификаций OpenGL.
Список зарегистрированных расширений можно найти в официальной базе расширений.
Дополнительные библиотеки
Существует ряд библиотек, созданных поверх или в дополнение к OpenGL. Например, библиотека GLU, являющаяся практически стандартным дополнением OpenGL и всегда её сопровождающая, построена поверх последней, то есть использует её функции для реализации своих возможностей. Другие библиотеки, как, например, GLUT и SDL, созданы для реализации возможностей, недоступных в OpenGL. К таким возможностям относятся создание интерфейса пользователя (окна, кнопки, меню и др.), настройка контекста рисования (область рисования, использующаяся OpenGL), обработка сообщений от устройств ввода/вывода (клавиатура, мышь и др.), а также работа с файлами. Обычно, каждый оконный менеджер имеет собственную библиотеку-расширение для реализации вышеописанных возможностей, например, WGL в Windows или GLX в X Window System, однако библиотеки GLUT и SDL являются кросс-платформенными, что облегчает перенос написанных приложений на другие платформы.
Библиотеки, как GLEW (>) и GLEE (>) созданы для облегчения работы с расширениями и различными версиями OpenGL. Это особенно актуально для программистов в Windows, так как, заголовочные и библиотечные файлы, поставляемые с Visual Studio, находятся на уровне версии OpenGL 1.1.
OpenGL имеет только набор геометрических примитивов (точки, линии, многоугольники) из которых создаются все трехмерные объекты. Порой подобный уровень детализации не всегда удобен при создании сцен. Поэтому поверх OpenGL были созданы более высокоуровневые библиотеки, такие как Open Inventor и VTK. Данные библиотеки позволяют оперировать более сложными трехмерными объектами, что облегчает и ускоряет создание трехмерной сцены.
Независимость от языка программирования
Для подтверждения независимости от языка программирования были разработаны различные варианты привязки (binding) функций OpenGL или полностью перенесены на другие языки. Одним из примеров может служить библиотека Java 3D, которая может использовать аппаратное ускорение OpenGL. Прямая привязка функций реализована в Lightweight Java Game Library, которая имеет прямую привязку OpenGL для Java. Sun также выпустила версию JOGL, которая предоставляет прямую привязку к C-функциям OpenGL, в отличие от Java 3D, которая не имеет столь низкоуровневой поддержки. Официальный сайт OpenGL имеет ссылки на привязки для языков Java, Fortran 90, Perl, Pike, Python, Ada и Visual Basic. Имеются также варианты привязки OpenGL для языков C++ и C#, смотрите.
История
Сегодня компьютерная графика нашла широкое распространение и применение в повседневной жизни. Ученые используют компьютерную графику для анализа результатов моделирования. Инженеры и архитекторы используют трехмерную графику для создания виртуальных моделей. Кинематографы создают удивительные спецэффекты или полностью анимированные фильмы (Shrek, Toy Story и др.). В последние годы широкое распространение получили также компьютерные игры, максимально использующие трехмерную графику для создания виртуальных миров.
Распространению компьютерной графики сопутствовали свои трудности. Лет 15 назад, разработка программного продукта, способного работать на большом количестве графического оборудования было сопряжено с большими временными и финансовыми затратами. Было необходимо отдельно создавать модули для каждого типа графических адаптеров, что порой приводило к большой дупликации исходного кода. Это сильно тормозило развитие и распространение компьютерной графики.
Silicon Graphics Incorporated специализировалась на создании высокотехнологического графического оборудования и программных средств. Являясь в то время лидером в трехмерной графике, SGI видела проблемы и барьеры в росте рынка. Поэтому было принято решение стандартизировать метод доступа к графической аппаратуре на уровне программного интерфейса.
Таким образом появился программный интерфейс OpenGL, который стандартизирует доступ к графической аппаратуре, путем смещения ответственности за создание аппаратного драйвера на производителя графического устройства. Это позволило разработчикам программного обеспечения использовать более высокий уровень абстракции от графического оборудования, что значительно ускорило создание новых программных продуктов и снизило на них затраты.
В 1992 году компания SGI возглавила OpenGL ARB - группу компаний по разработке спецификации OpenGL. OpenGL эволюционировал из 3D-интерфейса SGI - IRIS GL. Одним из ограничений IRIS GL было то, что он позволял использовать только возможности, поддерживаемые оборудованием; если возможность не была реализована аппаратно, приложение не могло её использовать. OpenGL преодолевает эту проблему за счёт программной реализации возможностей, не предоставляемых аппаратно, что позволяет приложениям использовать этот интерфейс на относительно маломощных системах…
Когда в 1995 году была выпущена библиотека Direct3D, Microsoft, SGI и Hewlett-Packard начали проект под названием Fahrenheit, который предусматривал создание более универсального программного интерфейса на основе Direct3D и OpenGL. Идея казалась достаточно обещающей, призванной навести порядок в области интерактивной трехмерной графики, однако в результате финансовых трудностей в SGI и отсутствии должной индустриальной поддержки проект был закрыт.
OpenGL 2.0
По сравнению с DirectX, говорили что главной проблемой OpenGL является Консорциум, в который входит большое количество компаний с различными интересами, что приводит к длительному периоду принятия новой версии спецификации. OpenGL версии 2.0 была представлена 3Dlabs в ответ на беспокойства относительно медленного развития и нечеткого направления OpenGL. 3Dlabs предложила ряд существенных дополнений к стандарту, наиболее значимым из которого был GLSL (OpenGL Shading Language). Это позволяет программисту заменить фиксированный конвейер OpenGL небольшими программами на специальном языке, GLSL, для создания таких эффектов, как «рельефные текстуры» («bump mapping»), волны и водная рябь. Финальная версия спецификации OpenGL 2.0 включает в себя поддержку GLSL. Однако, еще до введения в стандарт OpenGL языка GLSL существовала возможность разрабатывать спецэффекты на языках: assembler (расширения vertex_program, fragment_program) и Cg (NVidia C for Graphics). К сожалению многие предложенные возможности пока отсутствуют в версии OpenGL 2.0, хотя некоторые из них реализованы многими производителями в виде расширений.
Официальный сайт OpenGL
сайт 3Dlabs для разработчиков использующих OpenGL
сайт программирования для GPU
Neon Helium - Уроки по OpenGL
Теория 3D графики с примерами на OpenGL
Уроки с примерами для разработчиков игр. Предположим, что у нас есть объект, который должен двигаться к точке. Задачка-то простенькая, использовать интерполяцию, например. Но что, если наш объект может поворачиваться на случайный угол? Как тогда задать точку для интерполирования? Ведь наверняка наша условная вагонетка должна двигаться только по направлению своих колес. Соответственно либо тыльной, либо фронтальной стороной. С этой задачей нам поможет справиться векторная алгебра.

Теория

Мы приняли факт, что с помощью векторной алгебры данная задача разрешима. Значит, нам необходимо что-то делать с векторами. Но что? Для начала спроецируем понятие вектора на нашу задачу. По условию задачи нам нужно задать точку для интерполяции. То есть точку, относительно глобальной/локальной системы координат, в которую будет впоследствии двигаться объект. Значит отрезок между точкой объекта, которую мы приняли для задания движения, и конечной искомой точкой будет являться вектором.

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

  • координаты начала вектора;
  • длина вектора;
  • угол наклона к осям координат.
Предположим, что все это мы знаем. Тогда задача сводится к простейшим формулам теоремы синусов.

$inline$x/sin(α) = a/sin (90)$inline$
$inline$ x = a* sin(α)$inline$
$inline$y/sin (90 - α) = a/sin(90)$inline$
$inline$ y = a * sin (90 - α)$inline$

Где a - длина вектора, α - угол наклона к оси координат

Собственно, этих знаний нам пока достаточно для решения задачи на практике.

Практика

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

И в unity это тоже работает. Для начала, нам нужно определить четверти в сцене. Создаем куб в начале координат, перемещаем его и смотрим, какие координаты отрицательные, а какие положительные. В примере видно, что обе координаты отрицательные, значит куб находится в третьей четверти.

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

Void ChekingQuarterUp(Transform vectorAngle, ref Transform empty) { float zangle = 0; float xangle= 0; float zcoord = 0.0f; float xcoord = 0.0f; int normangle = Mathf.RoundToInt (vectorAngle.eulerAngles.y); if (normangle >= 0 && normangle <= 90) // 1-ая четверть { zangle = 90 - normangle; xangle = 0 - normangle; xangle = (xangle < 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 270 && normangle <= 360) // 2-ая четверть { xangle = 360 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 180 && normangle <= 270) // 3-ая четверть { xangle = 180 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle > 0) ? zangle * -1: zangle; } if (normangle > 90 && normangle <= 180) // 4-ая четверть { zangle = 90 - normangle; xangle = 180 - normangle; zangle = (zangle > 0) ? zangle * -1: zangle; xangle = (xangle < 0) ? xangle * -1: xangle; } zcoord = path * Mathf.Sin (zangle *Mathf.PI/180); xcoord = path * Mathf.Sin (xangle * Mathf.PI/180); float newpathx = empty.position.x + xcoord; float newpathz = empty.position.z + zcoord; empty.position = new Vector3 (newpathx, empty.transform.position.y, newpathz); }

Заключение

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

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

Пример реализации метода можно взять

1

Я работаю над игрой, которая будет бросать снаряд, реагирующий на физические силы. Я использую встроенную физику Unity в игре, но я рисую траекторию снаряда до его запуска. Для этого я использую LineRenderer и простой класс физики я свернутый вычислить позиции:

Public class SlingPhysics { private Vector3 HalfGravity; private float ForceMultiplier; public void Init(Vector3 gravity, float slingForce, float mass, float drag) { HalfGravity = gravity/2.0f; ForceMultiplier = slingForce/mass/(1 + drag); } public Vector3 GetPosition(Vector3 start, Vector3 direction, float timeDelta) { Vector3 pos = direction * (timeDelta * ForceMultiplier); pos.y += (HalfGravity.y * timeDelta * timeDelta); return start + pos; } ///

/// /// Starting Position /// /// Time increment of the samples /// /// Buffer to fill with positions public int GetPositions(Vector3 startPos, Vector3 direction, float timeIncrement, float yFloor, Vector3 positions) { int maxItems = positions.Length; int i = 0; for (; i < maxItems; i++) { Vector3 pos = GetPosition(startPos, direction, timeIncrement * i); if (pos.y < yFloor) break; positions[i] = pos; } return i; } }

Это прекрасно работает и (несколько удивительно) точно соответствует фактической траектории, что снаряд в конечном итоге путешествия при запуске и управляется двигателем Unity Physics.

Но теперь мы решили ввести перетаскивание на Жесткое тело, и траектория уже не идеальна. Я мог бы продолжать пытаться изменить свою физическую модель в соответствии с тем, что делает Unity, но это похоже на проигрышную битву.

Есть ли способ прекомпретировать и провести траекторию с использованием движка Unity Physics?

Если нет, то как осуществляется перетаскивание и угловое перемещение в математике Unity?

Есть ли источник документации для реализации физики Unity"s (5.3.4)?

1

Я искал то же самое, но не удалось найти официальную документацию. Однако достаточно просто проверить это самостоятельно. Я не помню с головы, но я использовал жесткое тело с величиной перетаскивания и один без него и написал простой скрипт для имитации перетаскивания и попробовал пару типичных формул, и это оказалось одним из простые. Тогда вам все равно придется вручную вычислять все, чтобы соответствовать реализации Unity, потому что они не предлагают API для того, что вы хотите. - Xarbrough 01 июн. 16 2016-06-01 23:39:21

0

Xarbrough, спасибо. Я выслежу формулу перетаскивания и попробую попробовать, несмотря на советы мудреца программиста, чтобы избежать глупости преследовать Единство. Мой код очень прост, поэтому немного сложнее не убьет меня; надеюсь, он кончается там. И когда выйдет следующий великий двигатель физики, я перейду через этот мост. - ThisGuy 02 июн. 16 2016-06-02 05:37:29

  • 2 ответа
  • Сортировка:

    Активность

2

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

Это действительно просто; ключевая часть заключается в следующем:

Velocity *= Mathf.Clamp01(1f - Drag * Time.fixedDeltaTime);

Пользовательский класс физики должен быть переработан, чтобы потребовать, чтобы приращение времени быть Time.fixedDeltaTime Юнити (время между FixedUpdate вызовов)

Public class SlingPhysics { private Vector3 Gravity; private float Force, Mass, Drag; public void Init(Vector3 gravity, float force, float mass, float drag) { Gravity = gravity; Force = force; Mass = mass; Drag = drag; } ///

/// Computes an array of Trajectory object positions by time. /// /// Number of positions filled into the buffer /// Starting Position /// Direction (and magnitude) vector /// Minimum height, below which is clipped /// Buffer to fill with positions public int GetPositions(Vector3 startPos, Vector3 direction, float yFloor, Vector3 positions) { float timeIncrement = Time.fixedDeltaTime; int maxItems = positions.Length; int i = 0; Vector3 velocity = direction * Force/Mass; Vector3 pos = startPos; for (; i < maxItems; i++) { velocity += Gravity * timeIncrement; velocity *= Mathf.Clamp01(1f - Drag * timeIncrement); pos += velocity * timeIncrement; if (pos.y < yFloor) break; positions[i] = pos; } return i; } }

5

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

Нет, не делайте этого. Всякий раз, когда Unity обновляется, материал физики, как этот разрыв. Например, физики Единства 4 и 5 не являются одними и теми же. Должен был сильно изменить мой физический код Unity 4, чтобы он работал правильно.

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

В режиме перетаскивания, стрелять Projectile2 (скрытый), а затем хранить его путь или положение (Vector3) он путешествовал через в List . Используйте этот сохраненный путь, чтобы нарисовать Projectile Trajectory .

Вам нужно только снять Projectile2 (спрятать) один раз и сохранить путь. Если во время режима перетаскивания, пальцевые, мыши или перетащить перемещаются в другую позицию, то вы должны ясный List , переснять Projectile2 (скрытые) еще раз, сохранить положение на List , а затем обновить Projectile Trajectory снова,