Comment éviter l'empilement de la vitesse de déplacement lorsque plusieurs touches sont enfoncées?

17

J'ai commencé un nouveau jeu qui ne nécessite pas de souris, laissant ainsi le mouvement au clavier. J'ai essayé d'incorporer 8 directions; haut, gauche, droite, haut-droite et ainsi de suite. Cependant, lorsque j'appuie sur plusieurs touches fléchées, la vitesse de déplacement se cumule ( http://gfycat.com/CircularBewitchedBarebirdbat ). Comment pourrais-je contrer cela?

Voici la partie pertinente de mon code:

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
la source
3
tangente: l'indentation dans votre code était un peu fouillée, donc je ne l'ai pas remarqué au début, mais les conditions dans votre code empêcheront la plupart de s'exécuter. Comme, si (UpArrow) else if (UpArrow && RightArrow) n'exécutera jamais la branche 'else'.
jhocking

Réponses:

13

Séparez votre code de sélection de direction du code de mouvement réel.

  1. Choisissez Directionen vérifiant quelles touches sont enfoncées. Stockez-le en tant que vecteur unitaire (normalisé).
  2. Multipliez votre Directionavec Speedet avec DeltaTime.
  3. Appliquez la transformation résultante à votre objet / caméra.
Kromster dit soutenir Monica
la source
27

Vous devez prendre la somme des directions, normaliser cela, puis multiplier par la vitesse.

J'ai répondu tangentiellement à cela dans le cadre de ma réponse à Empêcher les mouvements diagonaux

Plus précisément:

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
la source
3
Heheh, Larry serait fier! c2.com/cgi/wiki?LazinessImpatienceHubris
jzx
3
Notez que Unity fournit déjà des méthodes pour obtenir la magnitude et la magnitude au carré d'un vecteur.
Selali Adobor
1
Cela produit NaN si aucune touche n'est enfoncée
CodesInChaos
1
@jzx En effet, nous nous efforçons d'être comme les fameux Hobbits. youtube.com/watch?v=G49RUPv5-NU
Pharap
11

Le «vecteur de direction normalisé» est la façon dont cette tâche est généralement abordée et la façon dont je le fais souvent, mais dernièrement, j'ai simplement bloqué le vecteur de mouvement résultant. Il obtient généralement le même résultat final et le code est beaucoup plus 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);
}

Un code plus simple est presque toujours meilleur: E

jhocking
la source
Que fait ClampMagnitude, n'est-ce pas le même code que Normalize * Constantdans Disquise?
Kromster dit soutenir Monica
2
Pas assez. Le "serrage" d'une valeur garantit qu'elle reste dans une plage / inférieure au maximum, tandis que la normalisation définit la valeur sur une constante. Avec Unity au moins, GetAxis () renvoie des valeurs légèrement accélérées, vous donnant un mouvement plus fluide. La normalisation du vecteur remplace cette accélération, tandis que le serrage permet à l'accélération de se produire. C'est subtil mais plus joli. L'effet final est à peu près le même.
jhocking
1
+1 pour être la seule réponse écrite directement dans le contexte d'Unity. L'API fournit toutes sortes de méthodes mathématiques Vector / Quaternion utiles avec ce genre de situation à l'esprit, aucune raison de rouler la vôtre.
Selali Adobor
Je fixerais à 1 et multiplierais seulement moveSpeedaprès le serrage et éventuellement le fusionnerais avec la multiplication par deltaTime.
CodesInChaos
Ce changement gagne-t-il plus que la simple suppression d'une opération de multiplication? Par exemple, le serrage 1 fonctionne-t-il différemment du serrage 6? se demandant ce que fait votre changement ...
jhocking