Как избежать суммирования скорости движения при нажатии нескольких клавиш?


17

Я запустил новую игру, которая не требует мыши, оставляя движение до клавиатуры. Я попытался включить 8 направлений; вверх, влево, вправо, вверх-вправо и так далее. Однако, когда я нажимаю более одной клавиши со стрелкой, скорость движения увеличивается ( http://gfycat.com/CircularBewitchedBarebirdbat ). Как я мог противодействовать этому?

Вот соответствующая часть моего кода:

var speed : int = 5;

function Update () {
    if (Input.GetKey(KeyCode.UpArrow)) {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    } else if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.RightArrow)) {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    } else if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftArrow)) {
        transform.rotation = Quaternion.AngleAxis(315, Vector3.up);
    }
    if (Input.GetKey(KeyCode.DownArrow)) {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}

3
касательная: отступ в вашем коде был немного испорчен, поэтому я сначала не заметил, но условия в вашем коде будут препятствовать выполнению большей части его. Например, if (UpArrow) else if (UpArrow && RightArrow) никогда не будет запускать ветвь else.
Джоккинг

Ответы:


13

Отделите ваш код выбора направления от фактического кода движения.

  1. Выберите Direction, проверив, какие клавиши нажаты. Сохраните его как единичный (нормализованный) вектор.
  2. Умножьте ваши Directionна Speedи с DeltaTime.
  3. Примените полученное преобразование к вашему объекту / камере.

27

Вам нужно взять сумму направлений, нормализовать ее, а затем умножить на скорость.

Я косвенно ответил на это как часть моего ответа на Предотвращение диагонального движения

В частности:

velX = 0;
velY = 0;

if(keyLeft) velX += -1;
if(keyRight) velX += 1;
if(keyUp) velY += -1;
if(keyDown) velY += 1;

// Normalize to prevent high speed diagonals
length = sqrt((velX * velX ) + (velY * velY ));
if (length != 0)
{
    velX /= length;
    velY /= length;
}

velX *= speed;
velY *= speed;

3
Хе-хе, Ларри был бы горд! c2.com/cgi/wiki?LazinessImpatienceHubris
jzx

3
Обратите внимание, что Unity уже предоставляет методы для получения величины и квадрата вектора.
Селали Адобор

1
Это производит NaN, если никакие клавиши не нажаты
CodesInChaos

1
@jzx Действительно, мы стремимся быть похожими на легендарных хоббитов. youtube.com/watch?v=G49RUPv5-NU
Pharap

11

«Нормализованный вектор направления» - это то, как обычно выполняется эта задача, и как я часто это делаю, но в последнее время я просто ограничивал результирующий вектор движения. Обычно он достигает того же конечного результата, а код намного проще:

var moveSpeed = 6.0f;
function Update() {
  var movement = Vector3.zero;
  movement.x = Input.GetAxis("Horizontal") * moveSpeed;
  movement.z = Input.GetAxis("Vertical") * moveSpeed;
  movement = Vector3.ClampMagnitude(movement, moveSpeed);
  movement *= Time.deltaTime;
  transform.Translate(movement);
}

Более простой код почти всегда лучше: E


Что делает, ClampMagnitudeразве это не тот же самый код, что и Normalize * Constantв самом деле?
Кромстер говорит, что поддерживает Монику

2
Не совсем. «Зажим» значения гарантирует, что оно остается в диапазоне / ниже максимума, в то время как нормализация устанавливает значение в константу. По крайней мере, с Unity, GetAxis () возвращает слегка ускоряющиеся значения, обеспечивая более плавное движение. Нормализация вектора отменяет это ускорение, в то время как зажим позволяет ускорению произойти. Это тонкий, но выглядит лучше. Конечный эффект почти такой же, хотя.
Джоккинг

1
+1 за единственный ответ, написанный непосредственно в контексте Unity. API предоставляет все виды полезных математических методов Vector / Quaternion с учетом такого рода ситуаций, без каких-либо причин создавать свои собственные.
Селали Адобор

Я бы сжал до 1 и только moveSpeedумножил с после зажима и, возможно, слил бы его с умножением на deltaTime.
CodesInChaos

Получается ли это изменение больше, чем просто удаление одной операции умножения? Мол, зажим 1 работает иначе, чем зажим 6? интересно, что делает твое изменение ...
джохот
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.