Como evitar o empilhamento da velocidade de movimento quando várias teclas são pressionadas?

16

Comecei um novo jogo que não requer mouse, deixando o movimento para o teclado. Eu tentei incorporar 8 direções; para cima, esquerda, direita, direita e assim por diante. No entanto, quando eu pressiono mais de uma tecla de seta, a velocidade de movimento se acumula ( http://gfycat.com/CircularBewitchedBarebirdbat ). Como eu poderia neutralizar isso?

Aqui está parte relevante do meu código:

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
fonte
3
tangente: o recuo no seu código estava um pouco bagunçado, então eu não percebi no começo, mas as condições no seu código impedirão que a maioria dele seja executada. Por exemplo, if (UpArrow) else if (UpArrow && RightArrow) nunca executará o ramo 'else'.
jhocking

Respostas:

13

Separe seu código de seleção de direção do código de movimento real.

  1. Escolha Directionverificando quais teclas foram pressionadas. Armazene-o como um vetor unitário (normalizado).
  2. Multiplique seu Directioncom Speede com DeltaTime.
  3. Aplique a transformação resultante ao seu objeto / câmera.
Kromster diz apoio Monica
fonte
27

Você precisa tomar a soma das direções, normalizar isso e multiplicar pela velocidade.

Respondi tangencialmente a isso como parte da minha resposta a Impedir o movimento diagonal

Especificamente:

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
fonte
3
Heheh, Larry ficaria orgulhoso! Você pode usar o seguinte
código
3
Observe que o Unity já fornece métodos para obter a magnitude e a magnitude ao quadrado de um vetor.
você precisa saber é o seguinte
1
Isso produz NaN se nenhuma tecla for pressionada.
CodesInChaos
1
@jzx De fato, nós nos esforçamos para ser como os lendários Hobbits. youtube.com/watch?v=G49RUPv5-NU
Pharap
11

O "vetor de direção normalizada" é como essa tarefa geralmente é abordada e como eu frequentemente a faço, mas ultimamente eu tenho simplesmente pressionado o vetor de movimento resultante. Geralmente, obtém o mesmo resultado final e o código é muito mais simples:

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);
}

Código mais simples é quase sempre melhor: E

jhocking
fonte
O que ClampMagnitudefaz, não é o mesmo código que Normalize * Constantno disquise?
Kromster diz apoio Monica
2
Nem tanto. "Fixar" um valor garante que ele permaneça dentro de um intervalo / abaixo do máximo, enquanto a normalização define o valor como uma constante. Com o Unity, pelo menos, GetAxis () retorna valores ligeiramente acelerados, oferecendo um movimento mais suave. A normalização do vetor substitui essa aceleração, enquanto o aperto permite que a aceleração ocorra. É sutil, mas parece melhor. O efeito final é praticamente o mesmo.
jhocking
1
+1 por ser a única resposta escrita diretamente no contexto do Unity. A API fornece todos os tipos de métodos matemáticos úteis de Vector / Quaternion com esse tipo de situação em mente, sem motivo para você criar sua própria.
você precisa saber é o seguinte
Eu fixaria a 1 e só multiplicaria moveSpeeddepois da fixação e possivelmente a mesclaria com a multiplicação por deltaTime.
CodesInChaos
Essa mudança ganha mais do que apenas remover uma operação de multiplicação? Por exemplo, a fixação 1 funciona de maneira diferente da fixação 6? perguntando o que sua mudança de faz ...
jhocking