Bazı bağlamlardaki bazı nesnelerle çarpışmaları yoksay


14

Unity'de arabalarla yarış oyunu yapıyorum. Otomobilin bir takviye / nitro gücü var. Artırırken, zombilerle çarpışırken sapmak istemezdim, ama duvarlarla çarpışırken sapmak istiyorum.

Öte yandan, zombilerle çarpışmayı görmezden gelmek istemiyorum, çünkü yine de onlara darbe vurmak istiyorum.

Bunu nasıl ele almalıyım? Temel olarak, istediğim, arabanın belirli nesnelerle çarpışırken dönmemesi.

Yanıtlar:


7

Çalışma zamanında katmanlarınızı değiştirmeyi düşünün.

Tüm katmanlara sahip belirli nesneler için çarpışmaları etkinleştirme / devre dışı bırakma

Physics.IgnoreCollision ve Physics.IgnoreLayerCollision , sırasıyla iki çarpıştırıcı arasındaki ve iki katman arasındaki çarpışmaları devre dışı bırakmanıza olanak tanır.

Belirli bir çarpıştırıcıyı çarpışmalardan hariç tutmak istiyorsanız, bunu yapmanın yerleşik bir yolu yoktur. Tetikleyici olmayan çarpıştırıcılara sahip kinematik olmayan katı gövdeler kullanıyorsanız, yanıtları etikete göre filtrelemeye çalışsanız bile her zaman bir yanıt olacaktır.

Bunu projemizde başarma şeklimiz "Boşluk" adlı bir katman oluşturmaktı. Hiçlik hiçbir şeyle çarpışmaz.

Artık bir çarpıştırıcının çarpışmasını katmanını "Boşluk" olarak ayarlayarak geçici olarak devre dışı bırakabilir ve eski katmanını geri yükleyerek yeniden etkinleştirebilirsiniz.

İşte öz:

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

Bunu özellikle yaptık çünkü katı gövdelerin çocukları olan çarpıştırıcıların etkinleştirilmesi ve devre dışı bırakılması bazı durumlarda işleri gerçekten mahvedebilir. Böylece, bir bileşik rijit gövde çarpıştırıcısının bir parçasını güvenilir bir şekilde devre dışı bırakamazsınız, ancak bileşik çarpıştırıcı parçalarından birinin katmanı etrafında güvenilir bir şekilde takas yapabilirsiniz.

Şimdi sizin özel durumunuz

Zombi çarpışmasının arabanız üzerindeki etkisini azaltmak için, zombilerinizi kinematik katı gövdeyi tetiklemeyi veya başka bir deyişle kütlelerini çok küçük (float.Epsilon gibi) hale getirmeyi düşünün, bu nedenle etkinin otomobilin momentumu üzerinde sıfır etkisi vardır. Çarpma durumunda, bu katman anahtarını da yapabilirsiniz, böylece birincisi araba gövdesine ihmal edilebilir bir kuvvet uygulasa bile, sonraki çarpışmalar tetiklenmez.

Onları araba ile çarpışmayan bir katmana bile dönüştürebilirsiniz.

Ayrıca, zombilere koşarak devreye giren başka bir çarpıştırıcı da koyabilirsiniz. Bu şekilde OnTriggerEnter çarpma kuvvetlerini taklit edebilirsiniz. Bununla o kadar doğru olamazsınız, ancak temas normallerinin zombi eğlenceli bir yere atmak için yeterince iyi olabileceğini tahmin edebilirsiniz.

Kendinize şunu sormalısınız:

  • Arabamla etrafta dolaşan zombileri devirmek mi istiyorsunuz yoksa sadece bir ölüm animasyonu mu oynamalılar?

  • Arabanın hızının ve açısal hızının zombilere çarparak daha küçük şekillerde etkilenip etkilenmediğini umurumda mıyım?


1

Tüm zombilere Physics.IgnoreCollision'ı çağırın , araba güçlendirmeye başladığında oyuncu nesnesinin işlevini de geçirin. Bu, Unity'nin oyuncu ile zombiler arasındaki çarpışmalara tepki vermemesine neden olur. Araba güçlendirmeyi bitirdiğinde, Physics.IgnoreCollisionher zombi için tekrar arayın , oyuncu nesnesini geçirin ve falseçarpışma tepkisinin yeniden başlamasına neden olun.


Ancak bu, başka hiçbir şeyle çarpışmayacakları anlamına gelir.
Paul Manta

Biraz daha araştırma yapacağım. Aklıma gelen tek şey: OnCollisionEnter'dan false döndürerek çarpışmayı görmezden gelebilirsiniz?
Wackidev

@Wackidev Bu doğru değil.
Rhys van der Waerden

@ Paul Yanıtımı düzenledim.
Wackidev

0

Sanırım nesnelerin adlarını kontrol edebilir veya nesne sınıflarına bir ad değeri ekleyebilir ve sonra kontrol edebilirsiniz?

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

Daha sonra, güçlendirmeyi kontrol etmek ve kontrollere eklemek için kullanabileceğiniz başka bir değişkeniniz var.

EDIT: bu değişkeni içine ekledi.


Çarpışmalardan nasıl haberdar edileceğini biliyor; sonuç olarak herhangi bir işlem yapılmasını istemiyor. Bazı durumlarda yerleşik çarpışma yanıtını devre dışı bırakmak istiyor.
Wackidev

Şüphesiz çarpışma tetiklendiğinde ne olursa olsun köşeli parantezler arasına girer? Daha önce birlik kullanmadım, bu yüzden bilmiyorum ama cocos2d ve XNA'da böyle yapılır.
Lewis,

Aslında, Unity çarpışmaların kendisini PhysX aracılığıyla halleder. OnCollisionEnter sadece bir bildirim yöntemidir; gerçek çarpışma tepkisini ele almak için tasarlanmamıştır.
Wackidev

0

Bir şeyler çarpıştığında fizik motorunu şekil / kütleye göre otomatik olarak 'sapma' yapmak için kullandığınızı varsayıyorum? bu durumda, zombilerin kütlesini çok az bir değere değiştirin ve arabayı etkilemezler.


0

Burada iki cevap sınıfı vardır:

  1. Çarpışmaları yoksayma veya devre dışı bırakma
    • Bu çözümler sorunu çözmeyecek, vurulduğunda zombilerin uçmasını istiyor.
  2. Değişen kütle:
    • Bu iyi bir yaklaşım. Ataleti de buna göre değiştirmeyi unutmayın.
      • Alternatif olarak, yükseltme sırasında Kütle ve Atalet araçlarını değiştirebilirsiniz (bunu, yükseltme sırasında kinematik olmayan tüm nesnelerin bir araba üzerindeki etkisini azaltmak için yaparız)
      • Bu, bunların kinematik olduğunu varsayarak yolu veya duvarları etkilememelidir.

Bu yardımcı olur umarım!


Altı yıl önceki mevcut cevaplardan ikisi, burada önerdiğiniz kitle temelli yaklaşımı zaten tavsiye ediyor. Eklemek istediğiniz yeni bir strateji var mı?
DMGregory

Özür dilerim, henüz oy kullanamıyorum ve Paul Manta'nın yoldan çıkmadığından emin olmak istedim.
dwuLive
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.