Bagaimana cara menghindari penumpukan kecepatan gerakan ketika beberapa tombol ditekan?

16

Saya telah memulai permainan baru yang tidak memerlukan mouse, sehingga meninggalkan gerakan ke keyboard. Saya telah mencoba menggabungkan 8 arah; atas, kiri, kanan, atas kanan dan seterusnya. Namun ketika saya menekan lebih dari satu tombol panah, kecepatan gerakannya menumpuk ( http://gfycat.com/CircularBewitchedBarebirdbat ). Bagaimana saya bisa mengatasi ini?

Ini bagian yang relevan dari kode saya:

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
sumber
3
singgung: Lekukan dalam kode Anda sedikit kacau jadi saya tidak memperhatikan pada awalnya, tetapi kondisi dalam kode Anda akan mencegah sebagian besar dari itu berjalan. Seperti, jika (UpArrow) lain jika (UpArrow && RightArrow) tidak akan pernah menjalankan cabang 'lain'.
jhocking

Jawaban:

13

Pisahkan kode pilihan arah Anda dari kode gerakan aktual.

  1. Pilih Directiondengan memeriksa tombol mana yang ditekan. Simpan sebagai vektor satuan (dinormalisasi).
  2. Lipat gandakan Directiondengan Speeddan dengan Anda DeltaTime.
  3. Terapkan hasil transformasi ke objek / kamera Anda.
Kromster berkata mendukung Monica
sumber
27

Anda perlu mengambil jumlah dari arah, menormalkan itu, lalu kalikan dengan kecepatan.

Saya secara tangensial menjawab ini sebagai bagian dari respons saya terhadap Mencegah gerakan diagonal

Secara khusus:

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
sumber
3
Heheh, Larry akan bangga! c2.com/cgi/wiki?LazinessImpatienceHubris
jzx
3
Perhatikan bahwa Unity sudah menyediakan metode untuk mendapatkan besaran dan besarnya kuadrat dari suatu Vektor.
Selali Adobor
1
Ini menghasilkan NaN jika tidak ada tombol yang ditekan
CodesInChaos
1
@jzx Memang, kami berusaha untuk menjadi seperti Hobbit yang dongeng. youtube.com/watch?v=G49RUPv5-NU
Pharap
11

"Vektor arah dinormalisasi" adalah bagaimana tugas ini biasanya didekati, dan seberapa sering saya melakukannya, tetapi belakangan ini saya hanya menjepit vektor gerakan yang dihasilkan. Biasanya mencapai hasil akhir yang sama dan kodenya jauh lebih sederhana:

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

Kode yang lebih sederhana hampir selalu lebih baik: E

jhocking
sumber
Apa fungsinya ClampMagnitude, bukankah itu kode yang sama dengan Normalize * Constantdi disquise?
Kromster mengatakan mendukung Monica
2
Tidak terlalu. "Menjepit" nilai memastikan tetap dalam kisaran / di bawah maksimum, sementara normalisasi menetapkan nilai ke konstan. Dengan Unity setidaknya, GetAxis () mengembalikan nilai yang sedikit mempercepat, memberi Anda gerakan yang lebih halus. Normalisasi vektor menimpa percepatan itu, sementara penjepitan memungkinkan percepatan terjadi. Ini halus tetapi terlihat lebih bagus. Efek akhirnya hampir sama.
jhocking
1
+1 sebagai satu-satunya jawaban yang ditulis langsung dalam konteks Unity. API menyediakan semua jenis metode matematika Vektor / Quaternion yang berguna dengan situasi seperti ini dalam pikiran, tidak ada alasan untuk menggulung Anda sendiri.
Selali Adobor
Saya akan menjepit ke 1 dan hanya mengalikan dengan moveSpeedsetelah menjepit dan mungkin menggabungkannya dengan perkalian dengan deltaTime.
CodesInChaos
Apakah perubahan itu menghasilkan lebih dari sekadar menghapus satu operasi multiplikasi? Seperti, apakah penjepitan 1 beroperasi secara berbeda dari penjepitan 6? bertanya-tanya apa perubahan Anda ...
jhocking