Pengontrol karakter 2D dalam kesatuan (mencoba untuk mendapatkan platformer old-school kembali)

11

Hari ini saya mencoba membuat pengontrol karakter 2D dengan kesatuan (menggunakan phisics). Saya cukup baru di mesin fisik dan sangat sulit untuk mendapatkan kontrol yang saya cari. Saya akan sangat senang jika ada yang bisa menyarankan solusi untuk masalah yang saya temukan:

Ini adalah FixedUpdate saya sekarang:

public void FixedUpdate()
{
    Vector3 v=new Vector3(0,-10000*Time.fixedDeltaTime,0);
    _body.AddForce(v);

    v.y=0;
    if(state(MovementState.Left))
    {
        v.x=-_walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=-_maxWalkSpeed;
    }
    else if(state(MovementState.Right))
    {
        v.x= _walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=_maxWalkSpeed;
    }

    _body.velocity=v;

    Debug.Log("Velocity: "+_body.velocity);
}

Saya mencoba di sini untuk hanya menggerakkan tubuh kaku yang menerapkan gravitasi dan gaya linear untuk kiri dan kanan. Saya telah menyiapkan bahan fisik yang tidak membuat pantulan dan 0 gesekan saat bergerak dan 1 gesekan dengan diam. Masalah utama adalah bahwa saya memiliki colliders dengan lereng dan perubahan kecepatan dari naik (lebih lambat), menuruni lereng (lebih cepat) dan berjalan di collider lurus (normal). Bagaimana ini bisa diperbaiki? Seperti yang Anda lihat saya menerapkan allways kecepatan yang sama untuk sumbu x.

Untuk pemain saya memilikinya setup dengan posisi bola di kaki yang merupakan benda tegar yang saya lamar.

Tip lain yang bisa membuat hidup saya lebih mudah dengan ini disambut :).

PD Ketika pulang, saya perhatikan saya bisa menyelesaikan ini dengan menerapkan gaya konstan yang paralel ke permukaan pemain berjalan, tetapi tidak tahu apakah itu metode terbaik.

Tidak buruk
sumber
4
Platformer sekolah tua menggunakan "fisika kartun" yang disetel dengan tangan untuk mekanik lompat dan kontrol kecepatan langsung (mis. Tidak ada fisika sama sekali) untuk gerakan berjalan. Jika Anda dapat menulis ulang pengontrol karakter, lakukan itu, karena akan sulit untuk menyodok dan mendorong simulasi fisika yang licin ke dalam gerakan garing yang dimiliki permainan jadul.
Patrick Hughes
Masalah penulisan kustom adalah bahwa deteksi tabrakan hilang. Dan tidak mudah untuk membangunnya kembali tanpa menggunakan raycast (tergantung pada lingkungan, dll ... bisa jadi banyak dari mereka). Bagaimana Anda menangani situasi ini?
Notbad
Anda dapat memiliki collider pada hal-hal yang masih dianimasikan secara custom- ketika Anda menggunakan rigidbodies kinematic. Saya menjamin bahwa dalam kebanyakan situasi Anda tidak benar-benar menginginkan fisika / kekuatan dunia nyata dll untuk aplikasi semacam ini. Jika Anda mencari sudut pandang yang lebih teknis, mungkin teliti Human IK
Runonthespot
1
Def parit fisika dalam situasi ini.
Ray_Garner

Jawaban:

7

Jika Anda ingin meniru platformer sekolah tua, langkah pertama adalah membuang fisika sama sekali. Anda akhirnya akan bertarung dengan sistem fisika untuk mendapatkan gerakan platformer sekolah tua yang jelas tidak realistis. Lihat pengganti CharacterController ini yang membuang fisika sekaligus untuk mendapatkan ide bagus tentang satu cara untuk mengimplementasikannya.

prime31
sumber
3

Anda mungkin akan lebih bahagia dengan apa yang direkomendasikan mheona. Tetapi jika Anda akan menggunakan fisika Unity, maka Anda mungkin ingin menggunakannya ForceMode.VelocityChange.

Contoh:

public void FixedUpdate()
{
    var v = Vector3.zero;
    if(state(MovementState.Left))
    {
        v.x=-_walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=-_maxWalkSpeed;
    }
    else if(state(MovementState.Right))
    {
        v.x= _walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=_maxWalkSpeed;
    }

    _body.AddForce(v, ForceMode.VelocityChange);

    Debug.Log("Velocity: "+_body.velocity);
}

Anda juga harus menerapkan gravitasi global dalam pengaturan Fisika proyek Anda, dan untuk objek yang ingin Anda jatuh lebih cepat, tambahkan komponen Gaya Konstan .

ForceMode.Impulseserupa tetapi dipengaruhi oleh massa benda tegar. Membuatnya lebih sulit untuk disetel.

michael.bartnett
sumber
2

Bahkan jika Anda tidak suka komponen Pengontrol Karakter bawaan (seperti yang saya lakukan), lihat kode contoh Unity untuk Tutorial Gameplay 2D .

Kode mengimplementasikan gameplay 2D lengkap dengan platform bergerak, musuh dan kotak dengan tabrakan, menggunakan Pengontrol Karakter.

Tetapi jika Anda bahkan tidak ingin melihatnya, saya sarankan Anda untuk meminimalkan penggunaan fisika dan mencoba untuk menyalin perilakunya dengan kode Anda sendiri. Tergantung pada jenis game 2D yang Anda rencanakan, mungkin ini akan bekerja dengan cukup baik. Misalnya, alih-alih menerapkan kekuatan untuk Rigidbody.velocitymemindahkan karakter yang dapat Anda mainkan secara langsung Transform.Translate(), yang memindahkan objek Transform.positionberdasarkan porosnya. Anda bisa menentukan forwarddan backterkait dengan objek itu sendiri atau mungkin platform atau lantai Transform.up, sehingga Anda akan tahu apakah itu jalan dan jenis tahu sudutnya.

Juga jika Anda membuat semacam atribut kontrol kecepatan (mis. Berapa lama tombol ditekan) Anda dapat menerapkannya bersama dengan arah Anda sambil menerjemahkan untuk mencegah karakter Anda berjalan sesuatu yang terlalu condong tanpa kecepatan, seperti yang mereka lakukan pada Sonic the Hedgehog untuk Genesis / Mega Drive.

Jika Anda memilih untuk tetap menggunakan fisika saya tidak bisa membantu Anda sama sekali karena saya tidak begitu pandai dalam hal itu, tetapi perlu diketahui bahwa itu adalah perilaku normal untuk naik 'lereng' lebih lambat karena tubuh membutuhkan lebih banyak kekuatan untuk mengikuti , seperti kehidupan nyata.

mheona
sumber
Hal pertama yang saya baca ketika saya masuk ke kesatuan adalah tutorial itu. Masalahnya adalah bahwa kontrol terasa sangat buruk. Inilah sebabnya saya ingin mencari solusi sendiri. Di sisi lain ketika Anda mulai menggunakan Transform.Translate () itu tidak mudah untuk dilakukan lereng dan hal-hal lain. Anda harus melemparkan sinar beberapa kali (2 atau 3 untuk lantai, lebih banyak untuk arah Anda bergerak tergantung pada ukuran pahlawan). Untuk perangkat seluler raycast tidak baik, dan kurang jika Anda harus melakukan 5..n per iterasi deteksi tabrakan. Mungkin saya bisa salah, tapi saya rasa tidak.
Notbad
1

Apa yang Anda inginkan, Pengontrol Karakter bawaan . Dengan mengatur step offsetproperti pada komponen ini, Anda dapat membuat pemain bergerak naik dan turun dengan mudah.

NoobsArePeople2
sumber
Maaf karena tidak berkomentar saya tahu ada Pengontrol Karakter dalam persatuan dan saya telah menggunakannya beberapa kali, tapi saya tidak suka bagaimana perilakunya. Ini lebih cocok untuk FPS bukan game platform di mana mekanik gerak adalah salah satu hal yang paling penting.
Notbad
Saya pikir begitu Anda mengutak-atik pengaturan pada Character Controller itu berfungsi dengan baik. Apa yang Anda temukan kurang?
NoobsArePeople2
Hal pertama yang saya tidak suka adalah bahwa itu relatif lambat untuk benda kaku yang biasa dengan beberapa pemeran sinar. Mengetahui cara mencapainya, saya pikir saya bisa melakukan pengontrol yang lebih ringan. Masalah lain adalah menjadi kapsul / bola perilaku aneh di tepi platform (dapat diselesaikan dengan beberapa gips lagi). Inilah sebabnya saya ingin menggulung sendiri.
Notbad
0

masukkan deskripsi gambar di siniSaya kira itu karena gaya tidak sejajar dengan platform dan hasilnya berakhir dengan kenaikan yang lebih rendah dan penurunan yang lebih tinggi.

Jika Anda menerapkan gaya relatif ke sistem koordinat

AddRelativeForce

Anda ingin menjaga kecepatan maksimum dalam "x" dan membandingkannya dengan skalar, ingat bahwa kecepatan adalah vektor dan komposisi vx dan vy, di medan datar vy adalah nol, tetapi tentu saja pada lereng lebih besar dari nol.

Kecepatan berubah sesuai dengan arah tubuh, dan relatifnya berubah sehubungan dengan keseluruhannya

Ini dapat memodifikasi V Anda dengan cara yang tidak Anda inginkan juga:

if (Mathf.Abs (v.x)> _ maxWalkSpeed) v.x = _maxWalkSpeed;

mempertahankan VX global yang sama mungkin tampak aneh bagi mata. (Akselerasi yang Tidak Diinginkan)

NorbyAriel
sumber