¿Cómo evitar el apilamiento de la velocidad de movimiento cuando se presionan varias teclas?

16

Comencé un nuevo juego que no requiere mouse, dejando así el movimiento hasta el teclado. He intentado incorporar 8 direcciones; arriba, izquierda, derecha, arriba-derecha, etc. Sin embargo, cuando presiono más de una tecla de flecha, la velocidad de movimiento se acumula ( http://gfycat.com/CircularBewitchedBarebirdbat ). ¿Cómo podría contrarrestar esto?

Aquí está la parte relevante de mi 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
fuente
3
tangente: La sangría en su código estaba un poco desordenada, así que al principio no me di cuenta, pero las condiciones en su código evitarán que la mayoría de los códigos se ejecuten. Por ejemplo, if (UpArrow) else if (UpArrow && RightArrow) nunca ejecutará la rama 'else'.
jhocking

Respuestas:

13

Separe su código de selección de dirección del código de movimiento real.

  1. Elija Directionmarcando qué teclas se presionan. Almacénelo como un vector unitario (normalizado).
  2. Multiplica tu Directioncon Speedy con DeltaTime.
  3. Aplique la transformación resultante a su objeto / cámara.
Kromster dice que apoya a Mónica
fuente
27

Debe tomar la suma de las direcciones, normalizar eso y luego multiplicar por la velocidad.

Respondí tangencialmente esto como parte de mi respuesta a Prevenir el movimiento diagonal

Específicamente:

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
fuente
3
Jeje, ¡Larry estaría orgulloso! c2.com/cgi/wiki?LazinessImpatienceHubris
jzx
3
Tenga en cuenta que Unity ya proporciona métodos para obtener la magnitud y la magnitud al cuadrado de un Vector.
Selali Adobor
1
Esto produce NaN si no se presiona ninguna tecla
CodesInChaos
1
@jzx De hecho, nos esforzamos por ser como los legendarios Hobbits. youtube.com/watch?v=G49RUPv5-NU
Pharap
11

El "vector de dirección normalizado" es la forma en que generalmente se aborda esta tarea, y cómo lo hago a menudo, pero últimamente simplemente he estado sujetando el vector de movimiento resultante. Por lo general, logra el mismo resultado final y el código es mucho más simple:

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

El código más simple es casi siempre mejor: E

jhocking
fuente
¿Qué hace ClampMagnitude, no es el mismo código que Normalize * Constanten el disfraz?
Kromster dice que apoya a Mónica el
2
No exactamente. "Sujetar" un valor asegura que se mantenga dentro de un rango / debajo del máximo, mientras que la normalización establece el valor en una constante. Al menos con Unity, GetAxis () devuelve valores ligeramente acelerados, lo que le brinda un movimiento más suave. La normalización del vector anula esa aceleración, mientras que la sujeción permite que ocurra la aceleración. Es sutil pero se ve mejor. Sin embargo, el efecto final es prácticamente el mismo.
jhocking
1
+1 por ser la única respuesta escrita directamente en el contexto de Unity. La API proporciona todo tipo de métodos matemáticos útiles de Vector / Quaternion con este tipo de situación en mente, no hay razón para ti mismo.
Selali Adobor
Me fijaría a 1 y solo multiplicaría moveSpeeddespués de la fijación y posiblemente lo fusionaría con la multiplicación por deltaTime.
CodesInChaos
¿Ese cambio gana más que simplemente eliminar una operación de multiplicación? Por ejemplo, ¿la sujeción 1 funciona de manera diferente a la sujeción 6? preguntándose qué hace su cambio ...
jhocking