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

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);
    }
}
eren_tetik
источник
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;
JZX
источник
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

jhocking
источник
Что делает, ClampMagnitudeразве это не тот же самый код, что и Normalize * Constantв самом деле?
Кромстер говорит, что поддерживает Монику
2
Не совсем. «Зажим» значения гарантирует, что оно остается в диапазоне / ниже максимума, в то время как нормализация устанавливает значение в константу. По крайней мере, с Unity, GetAxis () возвращает слегка ускоряющиеся значения, обеспечивая более плавное движение. Нормализация вектора отменяет это ускорение, в то время как зажим позволяет ускорению произойти. Это тонкий, но выглядит лучше. Конечный эффект почти такой же, хотя.
Джоккинг
1
+1 за единственный ответ, написанный непосредственно в контексте Unity. API предоставляет все виды полезных математических методов Vector / Quaternion с учетом такого рода ситуаций, без каких-либо причин создавать свои собственные.
Селали Адобор
Я бы сжал до 1 и только moveSpeedумножил с после зажима и, возможно, слил бы его с умножением на deltaTime.
CodesInChaos
Получается ли это изменение больше, чем просто удаление одной операции умножения? Мол, зажим 1 работает иначе, чем зажим 6? интересно, что делает твое изменение ...
джохот