Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Unity 5 движение по кругу через поворот

#c_sharp #unity3d


Тело двигается по следующему алгоритму. Сначала выбирается случайный угол, на который
происходит поворот тела, затем задается Vector2.up и тело летит в направлении поворота.
Как сделать чтобы тело двигалось по кругу? Знаю, что необходимо использовать тригонометрические
функции, но как конкретно - не знаю. 
    


Ответы

Ответ 1



Вспоминаем геометрию. Уравнение окружности имеет вид: (x - a)² + (x - b)² = R² где a, b - координаты центра окружности R - радиус окружности Уравнение окружности радиуса R с центром в начале координат: x² + y² = R² Это поможет нам узнать переменные в другом представлении окружности: в параметрическом уравнении: x = R * cos(alpha) + a y = R * sin(alpha) + b в центре координат: x = R * cos(alpha) y = R * sin(alpha) Видим знакомые данные и еще дополнительную: alpha. Думаю понятно, что это угол. Меняем угол альфа и получаем движение по окружности. Все это переносим в Unity. Итак: public float angle = 0; // угол public float radius = 0.5f; // радиус public bool isCircle = false; // условие движения по кругу Допустим в какой-то момент времени нужно, чтоб объект начал движение по кругу, а значит нужно изменять постепенно угол и передавать значение в координаты. Угол можно менять например в Update, который будет каждый фрейм вызываться. Тогда получится простая формула: void Update () { if (isCircle) { angle += Time.deltaTime; // меняется плавно значение угла var x = Mathf.Cos (angle * speed) * radius; var y = Mathf.Sin (angle * speed) * radius; transform.position = new Vector2(x, y); } } Когда нужно прекратить движение по кругу, выставляем isCircle в false и обнуляем угол angle = 0; Всё. Для движения вокруг какого-то центра не забываем добавить это условие в координаты. Например центр с координатами 1, 1.5; Формула будет например такая: var x = Mathf.Cos (angle * speed) * radius; var y = Mathf.Sin (angle * speed) * radius; transform.position = new Vector2(x, y) + new Vector2(1, 1.5); По часовой или против часовой? Тут всё банально просто. Нужно одну из координат умножить дополнительно на -1. Если умножить X, то движение пойдет так, как будто находитесь на отметке 180° Если умножить Y, то с отметки 0°: Если я ничего не путаю)) Вот банальное и в очень сыром виде движение тела вперед, а при изменении параметра isCircle в true летит против часовой стрелки ровно с того места, где находится (для этого в формуле еще один параметр new Vector2(radius, 0) для компенсации направления движения). using UnityEngine; public class Testy: MonoBehaviour { public float angle = 0; public float speed = 1; public float radius = 0.5f; public bool isCircle = false; // запоминать свое нахождение и делать его центром окружности public Vector2 cachedCenter; void Update() { if (isCircle) { angle += Time.deltaTime; var x = Mathf.Cos(angle * speed) * radius; var y = Mathf.Sin(angle * speed) * radius; transform.position = new Vector2(x, y) + cachedCenter - new Vector2(radius, 0); } else { angle = 0; cachedCenter = transform.position; var x = transform.position.x; var y = transform.position.y; x += 0.5f * Time.deltaTime; transform.position = new Vector2(x, y); } } } Ну и по поводу движения по синусоиде. Тут немного по-другому. По одной оси мы просто движемся, а по другой, так сказать "вихляем". Я попробую просто написать две формулы, попробуйте разобраться с ними сами))) 1) Движение вперед, "вихляет" вниз-вверх: using UnityEngine; public class Testy2: MonoBehaviour { public float MoveSpeed = 0.5f; public float frequency = 3.0f; // Скорость виляния по синусоиде public float magnitude = 0.5f; // Размер синусоиды (радиус, по сути..можно заменить на "R") private Vector3 axis; private Vector3 pos; void Start() { pos = transform.position; axis = transform.up; } void Update() { pos += transform.right * Time.deltaTime * MoveSpeed; transform.position = pos + axis * Mathf.Sin(Time.time * frequency) * magnitude; } } 2) Движение вверх, "вихляет" влево-вправо: using UnityEngine; public class Testy2: MonoBehaviour { public float MoveSpeed = 0.5f; public float frequency = 3.0f; // Скорость виляния по синусоиде public float magnitude = 0.5f; // Размер синусоиды (радиус, по сути..можно заменить на "R") private Vector3 axis; private Vector3 pos; void Start() { pos = transform.position; axis = transform.right; } void Update() { pos += transform.up * Time.deltaTime * MoveSpeed; transform.position = pos + axis * Mathf.Sin(Time.time * frequency) * magnitude; } }

Комментариев нет:

Отправить комментарий