Я пытаюсь создать эффект, подобный эффекту Mario Galaxy или Geometry Wars 3, где, когда игрок ходит вокруг «планеты», гравитация, кажется, корректируется, и они не падают с края объекта, как если бы гравитация был зафиксирован в одном направлении.
(источник: gameskinny.com )
Мне удалось реализовать нечто, близкое к тому, что я ищу, используя подход, при котором объект, который должен иметь гравитацию, притягивает к нему другие твердые тела, но используя встроенный физический движок для Unity, применяя движение с помощью AddForce и тому подобное, Я просто не мог заставить движение чувствовать себя хорошо. Я не мог заставить игрока двигаться достаточно быстро без игрока, начинающего летать с поверхности объекта, и я не мог найти хороший баланс приложенной силы и силы тяжести, чтобы приспособиться к этому. Моя текущая реализация является адаптацией того, что было найдено здесь
Я чувствую, что решение, вероятно, по-прежнему будет использовать физику для заземления игрока на объект, если он должен покинуть поверхность, но как только игрок будет заземлен, появится способ привязать игрока к поверхности и отключить физику и управлять игроком с помощью других средств, но я действительно не уверен.
Какой подход я должен использовать, чтобы привязать плеер к поверхности объектов? Обратите внимание, что решение должно работать в трехмерном пространстве (в отличие от 2D) и должно быть реализовано с использованием бесплатной версии Unity.
Ответы:
Мне удалось выполнить то, что мне было нужно, в первую очередь с помощью этого поста в блоге для поверхностного осколка головоломки, и я предложил свои собственные идеи для движения игрока и камеры.
Привязка игрока к поверхности объекта
Базовая установка состоит из большой сферы (мир) и меньшей сферы (игрок) с прикрепленными к ним коллайдерами.
Основная часть выполняемой работы выполнялась следующими двумя методами:
Vector3 movementDirection
Параметр так же , как это звучит, направление мы будем двигаться нашим игроком в этом кадре, и вычисление этого вектора, а в конечном итоге относительно простой в этом примере, было немного сложно для меня , чтобы выяснить , в первую очередь. Подробнее об этом позже, но имейте в виду, что это нормализованный вектор в направлении, в котором игрок перемещает этот кадр.Поэтапно, первое, что мы делаем, это проверяем, попадает ли луч, исходящий из гипотетической будущей позиции, направленной к вектору игрока вниз (-transform.up), с помощью WorldLayerMask, который является общедоступным свойством LayerMask скрипта. Если вы хотите более сложные столкновения или несколько слоев, вам придется создать собственную маску слоя. Если радиопередача ударит по чему-либо, hitInfo используется для извлечения нормальной точки и точки попадания, чтобы вычислить новую позицию и вращение игрока, которое должно быть прямо на объекте. Может потребоваться смещение позиции игрока в зависимости от размера и происхождения рассматриваемого объекта игрока.
Наконец, это действительно только проверено и, вероятно, хорошо работает только на простых объектах, таких как сферы. Как следует из поста в блоге, на котором я основываю свое решение, вы, вероятно, захотите выполнить несколько лучевых трансляций и усреднить их для вашей позиции и поворота, чтобы получить более приятный переход при движении по более сложной местности. Могут быть и другие подводные камни, о которых я не думал в данный момент.
Камера и Движение
Как только игрок прилип к поверхности объекта, следующей задачей было движение. Первоначально я начал с движения относительно игрока, но столкнулся с проблемами на полюсах сферы, где направления внезапно менялись, заставляя моего игрока быстро менять направление снова и снова, не позволяя мне когда-либо проходить полюса. То, что я делал, заставляло моих игроков двигаться относительно камеры.
Для моих нужд было хорошо иметь камеру, которая бы точно следовала за игроком, основываясь исключительно на положении игроков. В результате, несмотря на то, что камера технически вращалась, нажатие вверх всегда перемещало плеер к верхней части экрана, вниз к нижней части и т. Д. Влево и вправо.
Для этого на камере, где целевым объектом был игрок, было выполнено следующее:
Наконец, чтобы переместить игрока, мы использовали преобразование основной камеры так, чтобы с нашими элементами управления вверх двигались вверх, вниз двигались вниз и т. Д. И именно здесь мы вызываем UpdatePlayerTransform, который привязывает нашу позицию к объекту мира.
Чтобы реализовать более интересную камеру, но элементы управления должны быть примерно такими же, как у нас здесь, вы можете легко реализовать камеру, которая не визуализируется, или просто другой фиктивный объект, чтобы основывать движение, а затем использовать более интересную камеру для рендеринга, что Вы хотите, чтобы игра выглядела так. Это обеспечит хорошие переходы камеры при обходе объектов без нарушения управления.
источник
Я думаю, что эта идея будет работать:
Сохраните копию планетарной сетки на стороне процессора. Наличие вершин сетки также означает, что у вас есть нормальные векторы для каждой точки на планете. Затем полностью отключите гравитацию для всех объектов, вместо этого применяя силу в направлении, совершенно противоположном направлению вектора нормали.
Теперь, на основании какой точки должен быть рассчитан этот нормальный вектор планеты?
Самый простой ответ (который, я уверен, сработает нормально) - приблизиться аналогично методу Ньютона : когда объекты появляются впервые, вы знаете все их начальные позиции на планете. Используйте эту начальную позицию, чтобы определить
up
вектор каждого объекта . Очевидно, гравитация будет в противоположном направлении (в направленииdown
). В следующем кадре, перед применением силы тяжести, направьте луч из новой позиции объекта в направлении его старогоdown
вектора. Используйте пересечение этого луча с планетой в качестве нового эталона для определенияup
вектора. Редкий случай попадания луча в ничто означает, что что-то пошло не так, и вы должны переместить свой объект туда, где он был в предыдущем кадре.Также обратите внимание, что при использовании этого метода дальнейшее происхождение игрока с планеты, чем хуже становится аппроксимация. Следовательно, лучше использовать где-нибудь вокруг ног каждого игрока в качестве источника. Я предполагаю, но я думаю, что использование ног в качестве источника также приведет к более легкой обработке и навигации игрока.
Последнее замечание: для достижения лучших результатов вы даже можете сделать следующее: отслеживать движение игрока в каждом кадре (например, используя
current_position - last_position
). Затем зафиксируйте егоmovement_vector
так, чтобы его длина по отношению к объекту былаup
равна нулю. Давайте назовем этот новый векторreference_movement
. Переместить предыдущийreference_point
наreference_movement
и использовать эту новую точку как трассировка лучей происхождения. После того, как (и если) луч достигнет планеты, перейдитеreference_point
к этой точке попадания. Наконец, рассчитать новыйup
вектор, из этого новогоreference_point
.Некоторый псевдокод, чтобы подвести итог:
источник
Этот пост может быть полезным. Суть в том, что вы не используете контроллеры персонажей, а создаете свои собственные, используя физический движок. Затем вы используете нормали, обнаруженные под игроком, чтобы ориентировать их на поверхность меша.
Вот хороший обзор техники. Есть много других ресурсов с такими терминами веб-поиска, как "прогулка в единстве по трехмерным объектам".
Также есть демонстрационный проект из unity 3.x, в котором был гуляющий двигатель, с солдатом и собакой и в одной из сцен. Это продемонстрировало ходьбу по трехмерным объектам Galaxy- style. Это называется локомоции runevision.
источник
вращение
Оформить ответ на этот вопрос на answers.unity3d.com (на самом деле задал сам). Quote:
Вот код, который он мне предложил:
Называйте это каждое обновление, и вы должны заставить его работать. (обратите внимание, что код в UnityScript ).
Тот же код в C # :
Сила тяжести
Для гравитации вы можете использовать мою «технику физики планет», которую я описал в своем вопросе, но она не очень оптимизирована. Это было просто то, что я подумал.
Я предлагаю вам создать собственную систему гравитации.
Вот учебник на Youtube от Себастьяна Лиги . Это очень хорошо работающее решение.
РЕДАКТИРОВАТЬ: В единстве перейдите в « Правка» > « Настройки проекта» > « Физика» и установите для всех значений силы тяжести значение 0 (или удалите твердое тело из всех объектов), чтобы предотвратить конфликт со встроенной гравитацией (которая просто тянет игрока вниз) индивидуальное решение. (выключи это)
источник