Як уникнути укладання швидкості руху при натисканні декількох клавіш?


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
дотична: відступ у вашому коді було трохи зіпсовано, тому я спочатку не помітив, але умови у вашому коді заважають більшості його працювати. Наприклад, якщо (UpArrow) інше, якщо (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 вже пропонує методи, щоб отримати величину та квадратичну величину вектора.
Selali Adobor

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 за єдину відповідь, написану безпосередньо в контексті Єдності. API надає всілякі корисні методи математики вектора / кватерніона, маючи на увазі подібну ситуацію.
Selali Adobor

Я moveSpeedзатиснув би на 1 і тільки помножую на після затискання і, можливо, об'єднаю його з множенням на deltaTime.
CodesInChaos

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