Abaikan tabrakan dengan beberapa objek dalam konteks tertentu

14

Saya membuat game balap dengan mobil di Unity. Mobil ini memiliki powerup boost / nitro. Sambil meningkatkan, saya tidak ingin menyimpang saat bertabrakan dengan zombie, tapi saya ingin disimpang saat bertabrakan dengan dinding.

Di sisi lain, saya tidak ingin mengabaikan tabrakan dengan zombie, karena saya masih ingin mengenai dampaknya.

Bagaimana saya harus menangani ini? Pada dasarnya, yang saya inginkan adalah agar mobil tidak berputar ketika bertabrakan dengan benda-benda tertentu.

Paul Manta
sumber

Jawaban:

7

Pertimbangkan untuk memanipulasi lapisan Anda saat runtime.

Mengaktifkan / menonaktifkan tabrakan untuk objek tertentu dengan seluruh lapisan

Physics.IgnoreCollision dan Physics.IgnoreLayerCollision memungkinkan Anda untuk menonaktifkan tabrakan antara dua colliders, dan antara dua layer, masing-masing.

Jika Anda ingin mengecualikan collider tertentu dari tabrakan, tidak ada cara untuk melakukannya. Jika Anda menggunakan benda tegar non-kinematik dengan collider non-pemicu, akan selalu ada respons meskipun Anda mencoba memfilter tanggapan dengan tag.

Cara kami mencapai ini pada proyek kami adalah dengan membuat layer bernama "Void". Void tidak bertabrakan dengan apa pun.

Sekarang Anda dapat menonaktifkan tabrakan collider untuk sementara waktu dengan mengatur layer-nya menjadi "Void", dan mengaktifkannya kembali dengan mengembalikan layer lamanya.

Inilah intinya:

int oldLayer = -1;
int voidLayer;

void Start()
{
    voidLayer = LayerMask.NameToLayer("Void");
}

void DisableCollider(Collider col)
{
    oldLayer = col.gameObject.layer;
    col.gameObject.layer = voidLayer;
}

void EnableCollider(Collider col)
{
    col.gameObject.layer = oldLayer;
}

Kami melakukan ini secara khusus karena mengaktifkan dan menonaktifkan colliders yang merupakan anak-anak dari rigidbodies benar-benar dapat mengacaukan segalanya dalam beberapa keadaan. Jadi Anda tidak dapat secara andal menonaktifkan bagian dari collider rigidbody majemuk, tetapi Anda dapat bertukar andal di sekitar lapisan salah satu bagian collider compound.

Sekarang situasi spesifik Anda

Untuk mengurangi dampak tabrakan zombie pada mobil Anda, pertimbangkan membuat zombie Anda menjadi benda tegar yang kinematik, atau membuat massa mereka sangat kecil (seperti float.Epsilon), sehingga dampaknya tidak memiliki efek nol pada momentum mobil. Pada benturan, Anda juga dapat melakukan layer switch ini, sehingga tabrakan berikutnya tidak terpicu, bahkan jika yang pertama menggunakan gaya yang dapat diabaikan pada bodi mobil.

Anda bahkan dapat mengubahnya menjadi lapisan yang tidak bertabrakan dengan mobil.

Anda juga bisa meletakkan collider lain di zombie yang diaktifkan di ran-over. Dengan cara ini Anda bisa memalsukan pasukan dampak OnTriggerEnter. Anda tidak bisa mendapatkan seakurat itu, tetapi Anda dapat memperkirakan di mana normals kontak cukup baik untuk melempar zombie ke suatu tempat yang menyenangkan.

Anda harus bertanya pada diri sendiri:

  • Apakah saya ingin dapat mengetuk zombie yang tertabrak dengan mobil saya, atau haruskah mereka memainkan animasi kematian?

  • Apakah saya peduli jika kecepatan mobil dan kecepatan sudut terpengaruh dengan cara yang lebih kecil dengan memukul zombie?

michael.bartnett
sumber
1

Panggil Fisika. IfgnoreCollision pada semua zombie, melewati fungsi objek pemain juga, ketika mobil mulai meningkatkan. Ini akan menyebabkan Unity tidak bereaksi terhadap benturan antara pemain dan zombie. Ketika mobil selesai meningkatkan, memanggil Physics.IgnoreCollisionlagi untuk setiap zombie, melewati objek pemain dan falsemenyebabkan tabrakan-respons untuk memulai lagi.

Wackidev
sumber
Tapi itu berarti mereka tidak akan bertabrakan dengan yang lain juga.
Paul Manta
Saya akan melakukan penelitian lebih lanjut. Satu-satunya hal yang dapat saya pikirkan adalah: mungkin Anda dapat mengabaikan tabrakan dengan mengembalikan false dari OnCollisionEnter?
Wackidev
@ Wackidev Ini bukan masalahnya.
Rhys van der Waerden
@ Paul Saya telah mengedit jawaban saya.
Wackidev
0

Saya kira Anda dapat memeriksa nama-nama objek, atau menambahkan nilai nama ke kelas objek kemudian memeriksa itu?

bool boosting = false; //need a trigger in the game to set this to true.

function OnCollisionEnter(theCollision : Collision)
{   
    if (boosting == true)
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit during boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit during boost");            
        }
    }
    else 
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit not in boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit not in boost");                
        }
    }
}

Kemudian gunakan variabel lain yang dapat Anda gunakan untuk memeriksa peningkatan dan menambahkannya ke cek.

EDIT: menambahkan variabel ini dalam.

Lewis
sumber
Dia tahu bagaimana diberitahu tentang tabrakan; dia hanya tidak ingin tindakan apa pun diambil sebagai hasilnya. Dia ingin menonaktifkan respons tabrakan bawaan dalam kasus tertentu.
Wackidev
Tentunya apa pun yang terjadi ketika tabrakan dipicu terjadi di antara kurung? Saya belum pernah menggunakan persatuan sebelumnya jadi saya tidak tahu tetapi di cocos2d, dan XNA dilakukan seperti itu.
Lewis
Sebenarnya, Unity menangani tabrakan itu sendiri melalui PhysX. OnCollisionEnter hanyalah metode pemberitahuan; itu tidak dirancang untuk menangani respons tabrakan yang sebenarnya.
Wackidev
0

Saya berasumsi Anda menggunakan mesin fisika untuk melakukan 'penyimpangan' secara otomatis berdasarkan bentuk / massa ketika semuanya bertabrakan? jika itu masalahnya, maka ubah massa zombie Anda ke nilai yang sangat minimal dan mereka tidak akan memengaruhi mobil.

ADB
sumber
0

Ada dua kelas jawaban di sini:

  1. Mengabaikan atau menonaktifkan tabrakan
    • Solusi ini tidak akan menyelesaikan masalah, ia ingin zombie terbang ketika terkena.
  2. Mengubah massa:
    • Ini pendekatan yang bagus. Jangan lupa juga untuk mengganti Inersia.
      • Anda dapat mengubah Massa dan Inersia mobil saat meningkatkan (kami melakukan ini untuk mengurangi dampak semua benda non-kinematik pada mobil saat meningkatkan)
      • Ini seharusnya tidak mempengaruhi jalan atau dinding dengan asumsi bahwa mereka kinematik.

Semoga ini membantu!

dwuLive
sumber
Dua dari jawaban yang ada dari enam tahun lalu sudah merekomendasikan pendekatan berbasis massa yang Anda sarankan di sini. Apakah ada strategi baru yang ingin Anda tambahkan?
DMGregory
Saya minta maaf, saya belum dapat memperbaiki dan saya ingin memastikan bahwa Paul Manta tidak menyesatkan.
dwuLive