Тело двигается по следующему алгоритму. Сначала выбирается случайный угол, на который происходит поворот тела, затем задается Vector2.up и тело летит в направлении поворота. Как сделать чтобы тело двигалось по кругу? Знаю, что необходимо использовать тригонометрические функции, но как конкретно - не знаю.
Ответ
Вспоминаем геометрию. Уравнение окружности имеет вид:
(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;
}
}
Комментариев нет:
Отправить комментарий