複数のキーが押されたときに移動速度のスタックを回避するにはどうすればよいですか?


16

私はマウスを必要としない新しいゲームを始めたので、動きはキーボードに任せています。私は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
タンジェント:コードのインデントが少しめちゃくちゃになっていたので、最初は気づきませんでしたが、コードの状態によってほとんどのコードが実行できなくなります。同様に、if(UpArrow)else if(UpArrow && RightArrow)は「else」ブランチを実行しません。
ジョッキング14

回答:


13

実際の移動コードから方向選択コードを分離します。

  1. Directionどのキーが押されているかを確認して選択します。単位(正規化された)ベクトルとして保存します。
  2. あなたを掛けDirectionSpeedとして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がすでに取得する方法を提供することに注意してください大きさ二乗大きさのベクトルのを。
セラリアドボール14

1
何もキーが押されていないされている場合、これははNaNを生成
CodesInChaos

1
@jzx実際、私たちは伝説のホビットのように努力しています。youtube.com/watch?v=G49RUPv5-NU
ファラプ14

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か、disquise と同じコードではありませんか?
Kromsterは、サポートモニカ14

2
そうでもない。値を「クランプ」すると、値が範囲内/最大値を下回らないようになり、正規化により値が定数に設定されます。少なくともUnityの場合、GetAxis()はわずかに加速する値を返し、よりスムーズな動きを実現します。ベクトルを正規化すると、その加速がオーバーライドされますが、クランプでは加速が可能になります。微妙ですが、見た目はきれいです。ただし、最終的な効果はほとんど同じです。
ジョーク14

1
+1は、Unityのコンテキストで直接記述された唯一の回答であるためです。APIは、このような状況を念頭に置いて、あらゆる種類の有用なVector / Quaternion数学メソッドを提供します。
セラリアドボール14

私は1にクランプしmoveSpeed、クランプ後にのみ乗算し、おそらく乗算で乗算しdeltaTimeます。
CodesInChaos 14

その変化は、1つの乗算演算を削除するだけではありませんか?同様に、クランプ1はクランプ6とは異なる動作をしますか?あなたの変更が何をするのか疑問に思っ...
jhocking
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.