Ігноруйте зіткнення з деякими об'єктами в певних контекстах


14

Я роблю гоночну гру з автомобілями в Unity. Автомобіль має прискорене / нітроеве харчування. Підвищуючись, я не хотів би відхилятися під час зіткнення із зомбі, але я хочу, щоб відхилявся при зіткненні зі стінами.

З іншого боку, я не хочу ігнорувати зіткнення із зомбі, тому що все одно хочу вразити їх ударом.

Як мені впоратися з цим? В основному, я хочу, щоб автомобіль не обертався при зіткненні з певними предметами.

Відповіді:


7

Подумайте про маніпулювання шарами під час виконання.

Увімкнення / відключення зіткнень для певних об'єктів цілими шарами

Physics.IgnoreCollision та Physics.IgnoreLayerCollision дозволяють вимкнути зіткнення між двома сутильниками та між двома шарами відповідно.

Якщо ви хочете виключити конкретний колайдер із зіткнень, для цього немає вбудованого способу. Якщо ви використовуєте некінематичні жорсткі тіла з не тригерними колайдерами, відповідь завжди буде, навіть якщо ви спробуєте відфільтрувати відповіді за тегом.

Як ми це зробили в нашому проекті, було створити шар під назвою "Порожнеча". Пустота взагалі ні з чим не стикається.

Тепер ви можете тимчасово відключити зіткнення колайдера, встановивши його шар на "Void", і повторно включити його, відновивши старий шар.

Ось суть:

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

Ми зробили це спеціально, тому що ввімкнення та вимкнення нападників, які були дітьми жорстких тіл, справді можуть викрутити справи за деяких обставин. Таким чином, ви не можете надійно відключити частину складеного жорсткого колайдера, але ви можете надійно поміняти навколо шару однієї із складених деталей колайдера.

Тепер ваша конкретна ситуація

Щоб зменшити зіткнення зомбі на ваш автомобіль, подумайте про те, щоб зробити ваших зомбі кінематичними триггерами жорстких тіл або інакше зробити їх масу дуже маленькою (як float.Epsilon), тому вплив має нульовий вплив на імпульс автомобіля. При ударі ви також можете зробити цей перемикач шару, щоб наступні зіткнення не спрацьовували, навіть якщо перше застосовує незначну силу до кузова автомобіля.

Ви навіть можете переключити їх на шар, який просто не стикається з автомобілем.

Ви також можете поставити інший колайдер на зомбі, які активізуються при перебігу. Таким чином ви можете підробити сили впливу OnTriggerEnter. Ви не можете бути настільки точними з цим, але ви можете визначити, де нормальні контакти, можливо, були достатньо хорошими, щоб кинути зомбі кудись весело.

Ви повинні запитати себе:

  • Я хочу, щоб я міг збити моїх автомобілів, що перебігли перебіг зомбі, чи вони просто грали в анімацію смерті?

  • Мені байдуже, чи на помірних впливах на швидкість та кутову швидкість автомобіля впливають зомбі?


1

Зателефонуйте Physics.IgnoreCollision на всіх зомбі, передаючи функцію гравцеві також, коли машина починає підсилювати. Це змусить Unity не реагувати на будь-які зіткнення між гравцем та зомбі. Коли автомобіль закінчується, викличте Physics.IgnoreCollisionще раз кожного зомбі, передавши йому об'єкт гравця, і викликайте falseзіткнення-реакцію, щоб почати заново.


Але це означає, що вони не зіткнуться ні з чим іншим.
Пол Манта

Я ще кілька досліджень. Єдине, про що я можу придумати: це, можливо, ви можете проігнорувати зіткнення, повернувши помилку з OnCollisionEnter?
Вакідев

@Wackidev Це не так.
Rhys van der Waerden

@Paul Я відредагував свою відповідь.
Вакідев

0

Я здогадуюсь, ви можете перевірити назви об’єктів або додати значення імен до класів об'єктів, а потім перевірити це?

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

Тоді просто є ще одна змінна, яку ви можете використовувати для перевірки на підвищення та додайте її до чеків.

EDIT: додано цю змінну в.


Він знає, як повідомити про зіткнення; він просто не хоче, щоб в результаті були вжиті будь-які дії. Він хоче відключити вбудовану реакцію на зіткнення в певних випадках.
Вакідев

Звичайно, що станеться, коли спрацьовує зіткнення, йде між дужками? Я раніше не використовував єдності, тому не знаю, але в cocos2d, і XNA зробив це так.
Льюїс

Власне, Unity керує зіткненнями через PhysX. OnCollisionEnter - це лише метод сповіщення; він не призначений для обробки реальної реакції на зіткнення.
Wackidev

0

Я припускаю, що ви використовуєте фізичний двигун, щоб зробити «відхилення» автоматично на основі форми / маси, коли речі стикаються разом? якщо це так, то змініть масу ваших зомбі на дуже мінімальне значення, і вони не вплинуть на машину.


0

Тут є два класи відповідей:

  1. Ігнорування або відключення зіткнень
    • Ці рішення не вирішать проблему, він хоче, щоб зомбі летіли при попаданні.
  2. Зміна маси:
    • Це хороший підхід. Не забудьте також змінити Інерцію відповідно.
      • Ви також можете змінити автомобілі Масса та Інерція під час прискорення (ми робимо це, щоб зменшити вплив усіх некінематичних об'єктів на автомобіль під час прискорення)
      • Це не повинно впливати на дорогу чи стіни, якщо вони є кінематичними.

Сподіваюся, це допомагає!


Два з існуючих відповідей шести років тому вже рекомендують масовий підхід, який ви пропонуєте тут. Чи хочете додати якусь нову стратегію?
DMGregory

Прошу вибачення, я ще не в змозі підтримати позицію, і я хотів переконатися, що Пол Манта не заблудив.
dwuLive
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.