Управление игрока волной, как в Geometry dash
Для моей игры нужно управление игрока волной, как в Geometry Dash. Но, я не знаю как это сделать. Если что волна нужна подобная :
Спасибо заранее!
Ответы (1 шт):
Вообще в GeometryDash это не основное управление, а лишь одно из множества дополнительных, но не важно...
Физика не подойдет
Насколько я помню в GD это движение не было физическим: смена направления происходила резко, то есть вряд ли получится реализовать это через изменение гравитации, так как тогда объект пойдет по параболе. Тогда можно сделать нефизическое движение.
Вариант №1: Translate на вектор
Самое простое, что можно сделать:
public Vector2 MovementDirection; // Направление движения
public float Speed; // Скорость
private void Start () {
MovementDirection.Normalize(); // 1
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyUp(KeyCode.Space))
MovementDirection.y *= -1; // 2
transform.Translate(MovementDirection.normalized * Speed * Time.deltaTime); // 3
}
// 1 — Нормализуем вектор, чтобы его длина была равна единице, и скорость передвижения задавалась исключительно переменной Speed // 2 — Изменяем направление, когда пробел нажали или отпустили. // 3 — Нефизическое передвижение. Домножаем на
Time.deltaTime, чтобы избавиться от привязки к FPS.
В этом случае, чем больше будет координата X в MovementDirection, тем быстрее объект будет двигаться вправо, чем больше Y, тем быстрее будет двигаться вверх-вниз, и наоборот. Математическим языком, выражение Y/X — тангенс угла наклона прямой полета
Обратите внимание, что в этом случае, благодаря нормализации, постоянным остается модуль именно вектора (общей) скорости, а не проекции этого вектора на ось X.
Вариант №2: Translate на угол
В этот раз будет использовать на вектор перемещения, а более понятную человеку характеристику — угол наклона.
public float SlopeAngle; // Угол наклона
public float Speed; // Скорость
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyUp(KeyCode.Space))
SlopeAngle *= -1; // Меняем угол наклона на противоположный при нажатии/отжатии пробела
Vector2 MovementVector = new Vector2(Speed, Speed * Mathf.Tan(SlopeAngle * Mathf.Deg2Rad));
transform.Translate(MovementVector * Time.deltaTime);
}
Важно домножить SlopeAngle на Mathf.Deg2Rad, чтобы перевести угол из градусов в радианы.
Само передвижение (последние две строки в Update) можно сделать немного по-другому:
Vector2 MovementVector = new Vector2(1, Mathf.Tan(SlopeAngle * Mathf.Deg2Rad));
transform.Translate(MovementVector * Speed * Time.deltaTime);
Чтобы не обращаться дважды к переменной Speed, домножим вектор на нее уже при передвижении.
Обратите внимание, что в этом случае постоянной будет именно проекция скорости на ось X, то есть "скорость вправо" будет постоянна вне зависимости от угла наклона, в отличие от предыдущего варианта.
Вы можете задавать угол не только в градусах. Вот несколько модификация варианта №2:
1) public float SlopeAngleRad; // Угол в радианах
2) Vector2 MovementVector = new Vector2(1, Mathf.Tan(SlopeAngle));
1) public float TgSlopeAngle; // Тангенс угла наклона (во сколько раз передвижение по Y будет больше передвижения по X за единицу времени)
2) Vector2 MovementVector = new Vector2(1, TanSlopeAngle);
1) public float CtgSlopeAngle; // Котангенс угла наклона (во сколько раз передвижение по X будет больше передвижения по Y за единицу времени).
2) Vector2 MovementVector = new Vector2(CtgSlopeAngle, 1);
- Под
1)указана переменная, контролирующая наклон, под2)— чему должен быть равен вектор движенияMovementVectorдля получения желаемого поведения. - Во всех трех модификациях предполагается, что домножение на скорость
Speedпроизводится непосредственно вtransform.Translate(). - Во всех трех модификациях варианта 2 постоянна именно проекция скорости на ось X вне зависимости от угла наклона.
