Как заблокировать один коллайдер за другим в Unity

Есть ли способ заблокировать один объект коллайдера за другим в 2D-игре Unity? У меня есть коллайдеры для врагов, идущих по экрану, но если враги проходят за барьерами (у которых есть свои собственные коллайдеры), вражеские коллайдеры все равно реагируют на пули игрока. Так что в основном я просто хочу разоблачать врагов только тогда, когда они не находятся за какими-либо барьерами. В настоящее время мои пули проходят через барьеры и обнаруживают врагов. Я разместил врагов и барьеры на отдельных панелях и слоях пользовательского интерфейса, но это просто их визуальное различение. С точки зрения столкновения, как мне сделать так, чтобы один (барьер) имел приоритет над другим (врагом)?

Просто используйте оператор if, чтобы уничтожить (или деактивировать при объединении) объект, если он сталкивается с барьером, прежде чем проверять, является ли он врагом. ---В вашей функции столкновения вы можете указать if (collider.gameObejct.tag == "Barrier") {//Уничтожить объект} else if (collider.gameObject.tag == "Enemy") {//Нанести урон врагу } .

DylanT 25 13.04.2023 15:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать методы Raycast. Вы можете бросить луч из позиции игрока в позицию врага, если он обнаружит стену посередине, вы не позволите им стрелять.

public LayerMask wallsLayer;

bool HasPathFreeOfWalls(Transform player, Transform enemy, float reticleRadius)
{
  Vector2 direction = enemy.position - player.position;
  Vector2 origin = player.position + (direction.normalized) * reticleRadius;
  float distance = direction.magnitude - reticleRadius;

  RaycastHit2D rayHit = Physics2D.Raycast( origin , direction, distance, wallsLayer);

  return rayHit.transform == null; // if does not hit anything, it means that the path is free of walls
}

Изменить, чтобы соответствовать описанию игры

Один из способов сделать это — сместить все коллайдеры так, чтобы они были выше опорных точек их соответствующих игровых объектов, например это.

Затем вы запускаете CircleCast вокруг сетки, чтобы обнаружить все объекты там, и проверяете, какой из них имеет самое низкое положение Y, то есть тот, который находится впереди. Так:

public LayerMask enemysAndWallsLayers;

bool HasEnemyInFront(Vector2 reticlePosition, float reticleRadius)
{
    RaycastHit2D[] enemysAndWallsHitted; // holds the results of the circle cast
    ContactFilter2D collisionFilter = new ContactFilter2D(); // filter user by the circleCast
    collisionFilter.layerMask = enemysAndWallsLayers;
    collisionFilter.useLayerMask = true;

    Physics2D.CircleCast(reticlePosition, reticleRadius, Vector2.zero, collisionFilter, enemysAndWallsHitted, 0);

    GameObject closestGameObject = null;
    float closestY = Mathf.Infinity;

    foreach(RaycastHit2D objHitted in enemysAndWallsHitted)
    {
        if (objHitted.transform.position.y < closestY)
        {
            closestY = objHitted.transform.position.y;
            closestGameObject = objHitted.transform?.gameobject;
        }
    }

    return closestGameObject != null && IsGameObjectEnemy(closestGameObject );
}

Функция IsGameObjectEnemy() должна быть реализована вами таким образом, чтобы вы могли определить, враг это или стена.

Извините, я не упомянул, но я использую сетку, чтобы указать на врагов. Так что, если я использую raycast, он будет проходить через все, что находится между игроком и прицельной сеткой.

mukul 13.04.2023 17:36

Я думаю, что сетка не будет проблемой, если вы убедитесь, что в wallLayer есть только стены. В любом случае, я изменил код, чтобы raycast начинался за пределами сетки.

Renan Ruan 13.04.2023 18:37

Мне нужно искать столкновения только вокруг сетки. Таким образом, даже если луч проходит через кучу стен, которые не окружают сетку, он не должен влиять на луч. Это шутер, и цели находятся вокруг прицельной сетки. Таким образом, если прицельная сетка указывает на врага, а перед врагом есть стена (так что здесь прицельная сетка указывает и на стену, и на врага), то стена должна закрывать врага. Если стена не окружает прицел и не закрывает врага, то она не должна влиять на луч. Я не уверен, как ваш модифицированный код справляется с этим. Пожалуйста, дополните. Спасибо!

mukul 13.04.2023 20:58

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

Renan Ruan 13.04.2023 21:08

Это статичный шутер от третьего лица, похожий на рассказы о стрелках, с сеткой (перекрестием), управляемой игроком. Таким образом, сетка перемещается повсюду на экране. Я устанавливаю сетку и стреляю. Все, что находится под прицелом, является целью. Если я установлю исходную точку луча рядом с игроком, он заденет все на пути (между игроком и прицельной сеткой).

mukul 14.04.2023 12:54

Теперь я понимаю! Я отредактировал свой ответ, чтобы он соответствовал этому описанию

Renan Ruan 14.04.2023 14:21

Я использую OverlapCircle вместо CircleCast, и вместо того, чтобы искать позицию y, я просто вручную устанавливаю маску слоя для вражеского контейнера как слой контейнера препятствия. Спасибо за руководство.

mukul 17.04.2023 18:21

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

В функции, которая проверяет столкновения, поместите проверку барьера перед проверкой врага. Например:

if (collider.gameObejct.tag == "Barrier") {//Destroy object} 
else if (collider.gameObject.tag == "Enemy") {//Damage enemy}

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

Надеюсь это поможет. Удачного кодирования!

Другие вопросы по теме