Игнорировать столкновения с некоторыми объектами в определенных контекстах

14

Я делаю гоночную игру с автомобилями в Unity. Автомобиль имеет усиление / нитро powerup. Во время повышения я бы не хотел отклоняться при столкновении с зомби, но я хочу отклоняться при столкновении со стенами.

С другой стороны, я не хочу игнорировать столкновения с зомби, потому что я все еще хочу бить их при ударе.

Как мне справиться с этим? По сути, я хочу, чтобы автомобиль не вращался при столкновении с определенными объектами.

Пол Манта
источник

Ответы:

7

Рассмотрите возможность манипулирования вашими слоями во время выполнения.

Включение / отключение столкновений для определенных объектов с целыми слоями

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

Если вы хотите исключить конкретный коллайдер из коллизий, нет встроенного способа сделать это. Если вы используете не кинематические твердые тела с не триггерными коллайдерами, ответ будет всегда, даже если вы попытаетесь отфильтровать ответы по тегу.

Мы выполнили это в нашем проекте, создав слой «Void». Пустота ни с чем не сталкивается.

Теперь вы можете временно отключить столкновение коллайдера, установив для его слоя значение «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. Вы не можете получить такую ​​точность, но вы можете приблизительно определить, где нормали контакта были достаточно хорошими, чтобы зомби бросили куда-нибудь веселое.

Вы должны спросить себя:

  • Хочу ли я иметь возможность сбивать разбитых зомби с моей машиной, или они должны просто играть анимацию смерти?

  • Меня волнует, влияют ли на скорость автомобиля и угловую скорость удары зомби?

michael.bartnett
источник
1

Вызвать Physics.IgnoreCollision для всех зомби, передав функцию объект-игрок, когда автомобиль начнет ускоряться. Это заставит Unity не реагировать на любые столкновения между игроком и зомби. Когда автомобиль завершит ускорение, позвоните Physics.IgnoreCollisionснова для каждого зомби, передавая ему объект игрока и falseвызывая реакцию столкновения снова.

Wackidev
источник
Но это будет означать, что они также не столкнутся ни с чем другим.
Пол Манта
Я сделаю еще несколько исследований. Единственное, о чем я могу думать: возможно, вы можете игнорировать коллизию, возвращая false из OnCollisionEnter?
Wackidev
@ Wackidev Это не тот случай.
Рис ван дер Варден
@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");                
        }
    }
}

Тогда просто есть другая переменная, которую вы можете использовать для проверки на повышение и добавить это к проверкам.

РЕДАКТИРОВАТЬ: добавил эту переменную в.

Льюис
источник
Он знает, как получать уведомления о столкновениях; он просто не хочет, чтобы в результате предпринимались какие-либо действия. Он хочет отключить встроенную реакцию на столкновение в некоторых случаях.
Вацидев
Конечно, что происходит, когда столкновение происходит между скобками? Я не использовал единство раньше, так что я не знаю, но в cocos2d, и XNA это сделано так.
Льюис
На самом деле, Unity сама обрабатывает столкновения через PhysX. OnCollisionEnter - это просто метод уведомления; он не предназначен для обработки фактического ответа на столкновение.
Вацидев
0

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

АБР
источник
0

Здесь есть два класса ответов:

  1. Игнорирование или отключение столкновений
    • Эти решения не решат проблему, он хочет, чтобы зомби полетели при попадании.
  2. Изменение массы:
    • Это хороший подход. Не забудьте также изменить инерцию соответственно.
      • В качестве альтернативы вы можете изменить массу и инерцию автомобилей при повышении (мы делаем это, чтобы уменьшить воздействие всех не кинематических объектов на автомобиль при повышении)
      • Это не должно влиять на дорогу или стены, предполагая, что они кинематические.

Надеюсь это поможет!

dwuLive
источник
Два из существующих ответов от шести лет назад уже рекомендуют массовый подход, который вы предлагаете здесь. Есть ли какая-то новая стратегия, которую вы хотите добавить?
DMGregory
Я извиняюсь, я пока не могу поднять голос и хотел убедиться, что Пол Манта не сбился с пути.
2