Движение объектов по определенной траектории с помощью математики
Предисловие
В этой статье я планирую рассказать вам, как математика и тригонометрические функции помогут вам сделать движение в вашей игре плавным и красивым. Я расскажу здесь про то, как заставить объект плавно поворачиваться в сторону цели с помощью Vector3.Lerp();, как заставить объект двигаться по траектории знака бесконечности и покажу еще много интересных примеров использования математики в подобных целях! Для демонстрации я буду использовать известный движок Unity, подкрепленный языком программирования C#, но поскольку эта статья больше про математику, а не про пользование конкретным языком/движком, вам не составит труда понять основную мысль и перенести все полученные знания в другую среду разработки.
Краткий экскурс в тригонометрию
Большую роль в этой статье будет играть тригонометрия, поэтому давайте быстренько пройдемся по основам, которые помогут вам понять, как работает все, что мы будем делать дальше.
Начнем с такой вещи как единичная окружность. Единичная окружность - это окружность с радиусом равным единице и с центром в начале координат. С помощью такой окружности можно легко показать, как образуется синус и косинус
см. единичная окружность
Теперь, после того, как мы посмотрели на единичную окружность, я предлагаю вам разобраться с синусом (его одного нам пока будет достаточно)
Если кратко и только по делу, синус - это тригонометрическая функция, которая принимает значение от -1 до 1 на единичной окружности. Давайте посмотрим, как постоянно увеличивающаяся градусная мера среднего угла единичной окружности образует синусоиду
Двигаем объект по разным траекториям
Сейчас, я думаю, многие поняли, что мы будем делать. Мы заставим объект двигаться по синусоиде! Для этого давайте напишем простой код на C#
Код
public GameObject obj; //Объект, который будет двигаться по синусоиде void Update() { obj.transform.position = new Vector2(0, Mathf.Sin(Time.time)); //Заставляем наш объект двигаться по синусоиде по оси Y }
//Если в среде разработки, которую вы используйте у вас нет доступа ко времени работы программы, то вы можете просто //создать переменную time и прибавлять к ней единицу каждый кадр. Работает это точно так же как в случае с Time.time в Unity.
Хорошо, теперь посмотрим, что у нас получилось:
Класс! Посмотрите как плавно перемещается наш объект, и это делается всего одной строчкой кода! Сразу в голове начинают появляться способы применения. Самый очевидный, как я думаю - анимация парящих объектов вроде вертолетов или летающих островов. Теперь давайте разберемся с тем, как менять характеристики нашей синусоиды. Давайте уменьшим амплитуду (высоту волны) и уменьшим длину волны (тем самым мы прибавим скорость)
Код
public GameObject obj; //Объект, который будет двигаться по синусоиде void Update() { obj.transform.position = new Vector2(0, A * Mathf.Sin(Time.time * L)); //Заставляем наш объект двигаться по синусоиде по оси Y }
Вместо A подставляем значение амплитуды. В данном случае это 0.5f Ну а вместо L подставляем скорость. Я подставил 4.
Смотрим результат:
Отлично, все работает так, как надо Теперь давайте будем двигать объект не только по оси Y но и по X. Только теперь нам пригодится косинус. Напишем следующий код:
Код
public GameObject obj; //Объект, который будет двигаться по синусоиде void Update() { obj.transform.position = new Vector2(0.5f * Mathf.Cos(Time.time * 4), 0.5f * Mathf.Sin(Time.time * 4)); //Заставляем наш объект двигаться по синусоиде по оси X и Y }
результат:
Движение по окружности!
Ну а самое интересное я оставил напоследок. Следующий код заставит объект двигаться по траектории знака бесконечности.
Код
public float speed = 4; public float scaleX = 1f; public float scaleY = 1f; float cornerAngle = 0; void Update() { cornerAngle += Time.deltaTime * speed; transform.position = new Vector3(Mathf.Cos(cornerAngle) * scaleX, Mathf.Sin(cornerAngle) * Mathf.Cos(cornerAngle) * scaleY, 0); }
Если вы хотите углубиться в то, как это работает, вот вам ссылка на википедию: Лемниската Бернулли
Lerp и Slerp
С тригонометрией на сегодня покончено. Поговорим о такой штуке как Lerp. Линейная интерполяция (Linear interpolation, Lerp — очень удобная функция при разработке игр, которая интерполирует значение в диапазоне от и до на основе параметра time, где time обычно находится в диапазоне от 0 до 1. Например, это можно использовать для резкого перемещения (прыжка) из одной точки в другую, либо для быстрого поворота объекта в сторону цели. Давайте напишем код, который будет перемещать объект из одной точки в другую с помощью Lerp.
Код
public float time; public Transform target; void Update() { transform.position = Vector3.Lerp(transform.position, target.position, time); }
Результат:
Тоже самое можно сделать и для поворота объекта к цели.
Код
public float time; public Transform target; void Update() { Vector3 dir = target.position - transform.position; Quaternion rotation = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Lerp(transform.rotation, rotation, time * Time.deltaTime); }
гифки не будет, так как я устал их делать
UPD: Если в вашей среде разработки отсутствует функция lerp, вот код, который находится внутри Vector3.Lerp(); в Unity
Код
public static Vector3 Lerp(Vector3 a, Vector3 b, float t) { t = Mathf.Clamp01(t); return new Vector3(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t); }
Кроме Lerp есть еще и Slerp. По идеи, это тоже самое, но только двигаться наш объект будет не по прямой, а по окружности. Напишем код, идентичный предыдущему, только заменим Lerp на Slerp
Код
public float time; public Transform target; void Update() { transform.position = Vector3.Slerp(transform.position, target.position, time); }
Вот какой интересный результат у нас получился:
Пожалуй, на этом мы и остановимся. Надеюсь, что после прочтения этой статьи вы смогли подчеркнуть для себя что-нибудь интересное, что будет делать ваши игры лучше, а сейчас на этом все. Благодарю вас за время, уделенное этой статье и прощаюсь. Пока!
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Движение объектов по определенной траектории с помощью математики», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.
Согласен. Технологии очень быстро шагают вперед. Недавно посмотрел, как компьютер рассчитывает тригонометрические функции на низком уровне. Ужас какой-то =)