Как сделать чтобы один коллайдер игнорировал другой

Добавил пользователь Евгений Кузнецов
Обновлено: 04.10.2024

Создание объекта, контролируемого игроком, требует наличия определенных элементов: спрайт, способ управления им и способ его взаимодействия с игровым миром. Рассмотрим этот процесс шаг за шагом и начнем, пожалуй, со спрайта. Вот изображение, которое мы будем использовать:

  1. Скорируйте картинку в папку "Textures"
  2. Создайте новый спрайт и назовите его "Player"
  3. Настройте спрайт так, чтобы он отображался в свойстве "Sprite" компонента "Sprite Renderer"

Если у вас возникли проблемы, обратитесь к предыдущему уроку. Мы проделали точно такие же действия для фона и "реквизита".

  1. Поместите игрока в слой "2 - Foreground"
  2. Измените масштаб на (0.2, 0.2, 1)

Теперь несколько слов о компонентах. Мы только что говорили о компоненте "Sprite Renderer". Если вы еще не заметил, объект игры состоит из нескольких компонентов, видимых в панели "Инспектор".

По умолчанию пустой объект игры выглядит так:

Компоненты пустого игрового объекта

Этот объект имеет только один компонент: Transform . Этот компонент является обязательным и не может быть отключен или удален. Вы можете добавить к объекту столько компонентов, сколько захотите. Например, скрипты добавляются в качестве компонента. Большинство компонентов может быть включено или отключено пока существует объект.

Включить компонент игрового объекта

(Вы можете нажать на галочку чекбокса, чтобы отключить его. Вы можете щелкнуть правой кнопкой мыши на компоненте, чтобы вернуть прежнее свойство, удалить его и т.д.

Компоненты могут взаимодействовать с другими компонентами. Если объект имеет сомпонент, который требуется другому компоненту объекта для работы, вы можете просто перетащить весь объект внутрь этого компонента, и тогда компонент сам найдет все, что ему нужно.

Sprite Renderer является компонентом, который способен отображать спрайт-текстуру. Теперь, когда мы узнали о концепции компонента, давайте добавим один к игроку!

Добавляем бокс-коллайдер (Box Collider)

Нажмите на кнопку "Добавить компонент" объекта игрока. Выберите "Box Collider 2D". Вы можете увидеть коллайдер в редакторе "Сцена" зрения и настройки его размера в "Инспекторе" в поле "Размер" (Size).

Существует еще один способ редактирования бокс-коллайдера. Выберите игровой объект с помощью бокс-коллайдера и зажмите клавишу shift на клавиатуре. Вы увидите, что на бокс-коллайдере (зеленый прямоугольник ) появились четыре маленьких рычажка. Перетащите один из них, чтобы изменить форму бокс-коллайдера. Будьте осторожны, синий прямоугольник представляет собой компонент Transform вашего игрового объекта, а не коллайдер.

Мы будем устанавливать размер коллайдера равным (10, 10) .

Это слишком много для настоящего шмапа, но все же меньше, чем спрайт:

Хитбокс игрока

В настоящее время, этого вполне достаточно.

Совет: Если вы планируете создать шмап, вам придется уделить много времени настройке хитбоксов – они должны точно соответствовать маленькому элементу внутри игрового спрайта. Вы также можете изменить такой параметр коллайдера, как shape – например, с помощью "Circle Collider 2D". Благодаря Unity, его поведение при этом не меняется, но это позволяет немного улучить геймплей.

Сохраним объект игрок как префаб. Теперь у вас есть базовую сущность игрока!

Добавляем спрайт игрока

2D полигональный коллайдер

Если вы хотите супер точный и произвольный формы хитбокс, воспользуйтесь компонентом Unity "Полигоннальный коллайдер 2D" (Polygon Collider 2D). Эффект от этого будет незначительный, но зато вы получите такую форму, какую вы хотите.

"Polygon Collider 2D" похож на остальные коллайдеры: вы можете изменять форму с помощью мышки в режиме "Scene". Для удаления точки зажмите cmd или ctrl , а чтобы отрегулировать положение точки или добавить ее в форму коллайдера, используйте shift

Магия Rigidbody

Последний компонент, необходимый для добавления на нашего игрока: "Rigidbody 2D". Это поможет физическому движку правильно задействовать объект в игровом пространстве. Более того, это позволит вам использовать столкновения в скрипте.

  1. Выберите объект Player в "Hierarchy".
  2. Добавьте компонент "Rigidbody 2D".

Теперь, нажмите кнопку "играть" и смотрите, что у нас вышло:

Корабль падает! И как падает! Передвайте привет нашей любимой силе тяжести. По мере того, как сменяются кадры с заранее заданной гравитацией и rigidbodies прибавляет объекту массы, корабль притягивается к нижней части экрана.

По-умолчанию, ускорние свободного падения в Unity равно 9.81 , т.е. мы имеем дело с земной гравитацией.

Гравитация может быть использована в любой игре, но нам она не нужна. К счастью, гравитацию на Rigidbody можн легко отключить. Просто установите "гравитационный масштаб" равным нулю. Вот и все, корабль снова летит. Не забудьте поставить галочку в окошке "Fixed Angles", чтобы предотвратить вращение корабля, обусловленное такой физикой.

Настройки твердого тела игрока

Перемещение игрока

"Sync MonoDevelop Project": Это подменю немного странное.Во-первых, невозможно изменить имя, даже если сменить редактора.
Мы также рекомендуем использовать это меню при создании первого скрипта, так как Unity создаст решения и привяжет их к библиотекам Unity (для Visual Studio, Xamarin Studio или MonoDevelop).
Если вместо этого вы просто откроете скрипт, компилятор вашего IDE, скорее всего, зарегистрирует определенные ошибки, не Unity. Это не имеет значения, потому что вам не придется использовать его напрямую, но функция автоматического завершения объектов Unity не помешает.

По умолчанию в скрипте уже прописаны методы Start и Update . Вот краткий список наиболее часто используемых функций:

  • Awake() вызывается один раз, когда объект создается. По сути аналог обычной функции-конструктора.
  • Start() выполняется после Awake() . Отличается тем, что метод Start() не вызывается, если скрипт не включен (remember the checkbox on a component in the "Inspector").
  • Update() выполняется для каждого кадра in the main game loop.
  • FixedUpdate() вызывается каждый раз через определеннок число кадров. Вы можете вызывать этот метод вместо Update() когда имеете дело с физикой ("RigidBody" и др.).
  • Destroy() вызывается, когда объект уничтожается. Это ваш последний шанс, чтобы очистить или выполнить код.

У вас также есть некоторые функции для обработки столкновений:

  • OnCollisionEnter2D(CollisionInfo2D info) выполняется, когда коллайдер объекта соприкасается с другим коллайдером.
  • OnCollisionExit2D(CollisionInfo2D info) выполняется, когда коллайдер объекта не соприкасается ни с одним другим коллайдером.
  • OnTriggerEnter2D(Collider2D otherCollider) выполняется, когда коллайдер объекта соприкасается с другим коллайдером с пометкой "Trigger".
  • OnTriggerExit2D(Collider2D otherCollider) выполняется, когда коллайдер объекта перестает соприкасаться с коллайдером, помеченным как "Trigger".

Итак, с теорией покончено, пора в бой. Или нет, погодите еще немного: обратите внимание, что почти все, о чем мы говорили с вами имеет, суффикс "2D". Box Collider 2D , a Rigidbody 2D , OnCollisionEnter2D , OnTriggerEnter2D и т.д. Эти новые компоненты или методы появились с Unity 4.3. Используя их, вы работаете с физическим движком, встроенным в Unity 4.3, для 2D-игр (на основе Box2D) вместо движка для 3D-игр (PhysX). Два движка имеют аналогичные концепции и объекты, но они не работают точно так же. Если вы начинаете работать с одним (например, Box2D для 2D-игр), придерживаqntcm его. Именно поэтому мы используем все объекты или методы с суффиксом "2D".

В скрипт для нашего игрока мы добавим несколько простых элементов управления, а именно: клавиши со стрелками, которые будут перемещать корабль.

Поясню цифры в комментариях к коду:

  1. Сначала определим публичную переменную, которая будет отображаться в окне "Инспектор". Это скорость, используемая для корабля.
  2. Сохраним движение для каждого кадра.
  3. Используем дефолтную ось, которую можно отредактировать в "Edit" -> "Project Settings" -> "Input". При этом мы получим целые значения между [-1, 1] , где 0 будет означать, что корабль неподвижен, 1 - движение вправо, -1 - влево.
  4. Умножим направление на скорость.
  5. Изменим скорость rigidbody. Это даст движку команду к перемещению объекта. Сделаем это в FixedUpdate() , предназначенном для всего, что связано с физикой.

Теперь добавим скрипт к игровому объекту. Для этого перетащите скрипт из окна "Проект" (Project) на игровой объект в "Иерархии" (Hierarchy). Вы также можете нажать на "Add Component" и добвить его вручную.

Попробуйте настроить скорость: нажмите на игрока, измените значения скорости в "Инспекторе", и посмотрите что из этого получится.

Инспектор для сценария

Будьте осторожны: изменения параметров, сделанные во время, игры теряются, когда вы ее остановите! Инспекторе - это отличный инструмент для настройки геймплея, но запомните или запишите, что вы делали, если хотите сохранить изменения. Этот же трюк подходит, если вы хотете проверить что-то новое, но не хотите вносить изменения в реальный проект.

Первый враг

Теперь добавим неприятелей, стремящихся уничтожить наш корабль. Пусть им будет зловещий спрут, названный "Poulpi":

Poulpi Sprite

Создадим новый спрайт. Для этого:

  1. Скопируйте картинку в папку "Textures".
  2. Создайте новый спрайт, используя это изображение.
  3. Измените свойство "Масштаб" (Scale) в разделе Трансформирование (Transform) на (0.4, 0.4, 1) .
  4. Добавьте "Box Collider 2D" размером (4, 4) .
  5. Add a "Rigidbody 2D" with a "Gravity Scale" of 0 and "Fixed Angles" ticked.

Сохраните префаб и. вуаля!

Спрайт врага в Unity

Скрипт

Теперь напишем простенький скрипт, отвечающий за движение осьминога в определенном направлении. Для этого создайте новый скрипт, назвав его "MoveScript".

Модульность обеспечивается системой на основе компонентов Unity. Это отличный способ отделить друг от друга скрипты с различными функциями. Конечно, вы можете написать один гигантский скрипт с большим количеством параметров. Это ваш выбор, но я настоятельно не рекомендую вам делать это.

Скопируем некоторые части кода, который мы написали в «PlayerScript" для движения персонажа. We will add another designer (a public member you can alter in the "Inspector") variable for the direction:

Прикрепите скрипт к осьминогу. Нажмите "Play" и убедитесь, что спрут движется так, как показано на рисунке ниже:

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

Вы узнали, как добавить игрока, движущегося с помощью клавиатуры. Также, мы создали врага с зачаточным AI. Теперь мы хотим иметь возможность уничтожить его! А для этого, нам нужны боеприпасы, которые мы создадим в следующем уроке 2D игра на Unity. Подробное руководство. Часть 3.

Не так редко нам бывает нужно менять свойства коллизии объектов в игровом движке Unity 3D. Давайте разберемся, как отключать коллайдеры, чтобы сделать объект невосприимчивым к соприкосновениям с другими коллайдерами.


Итак, для начала мы получим компонент BoxCollider с помощью вызова команды GetComponent:

Далее обращаемся к свойству enabled, которое отвечает за активность объекта и ставим ему false:

Готово! Чтобы вернуть все обратно, нужно вызвать эту же команду, но false поменять на true.

В основном у меня есть зоны телепорта, созданные для доступа к новым областям внутри уровня. Это только должно отвечать на коллайдер BoxObject. Тем не менее, я прикрепил куб к Игроку, отключил рендеринг сетки и использовал его коллайдер для обнаружения врагов. К сожалению, обнаруженный вражеский коллайдер касается зоны телепорта и превращает меня в новое положение задолго до того, как мои Телепорты приблизятся к нему. Я попытался изменить тег на коллайдере обнаружения противника, но он все еще редактирует -> Настройки проекта -> Физика.

Как мне заставить объект телепорта игнорировать коллайдер обнаружения противника?

Измените Layer Collision Matrix слой игрока Player . Затем создайте новый слой Teleports . Перейдите к Player . Затем, внизу Teleports , в Player строке снимите отметку со всего, кроме столбца под Player .

Теперь объекты в Teleports слое будут сталкиваться только с объектами в Player проигрывателе.

Поскольку стрельба у меня осуществляется при помощи RayCast, возникла вот такая проблема:

Персонажи НПс(враги) имеют 2 коллайдера: свою собственную для определения столкновений, и sphere Collider, кторый работает как триггер(он необходим, т.к при входе в него враги реагируют на появление ГГ). Так вот, кгда начинаешь по ним стрелять — луч Raycast врезается в огромный sphere collider, и ищет у обьекта с этим коллайдером скрипт HP)) получается что целиться даже не обязательно во врагов — коллайдеры сферы огромные

как можно это вылечить?

у меня есть несколько додумок, но незнаю как это в скрипте написать..

ведь есть возможность заставить RayCast игнорировать триггеры?или допустим игнорировать все коллайдеры типа Sphere collider?Если можно, прошу помочь с кодом.

Вот код Raycast-а:

Ray ray = new Ray(cam.position, cam.forward);//выстрел луча из координат камеры

if (Physics.Raycast(ray,out hit, speed))//при столкновении луча

Debug.Log(hit.collider.name);//показать имя с чем столкнулись

waruiyume 14 авг 2012, 20:06

Засунуть сферы в другой слой и использовать Raycast с маской слоёв, или Edit->Project Settings->Physics

KorsaiR 15 авг 2012, 05:39

Спасибо))теперь всё как надо

djon801 16 дек 2014, 08:30

Кто потскажет как быть?

Есть два колайдера один в одном.и тогог и другого надо тпроверять именно лучем,тоесть один одну функцию выполняет другой другую лучь с мыши .

Маска не потходит.ужны активные оба колайдера.

Может я в масках не понял чтото .растолкуйте как можно щюпать оба колайдера но при этом чтоб они не мешали друг другу

mastersmit 16 дек 2014, 12:13

Чет мне кажется проверять дистанцию до игрока проще, чем проверять с помощью триггера..

piligrin 16 дек 2014, 17:05

Если один коллайдер в другом, то расстояние между ними невелико.Можно попробовать проверять столкновение луча с одним коллайдером и потом отсылать результат в нужное место(скрипт) с нужными последствиями, типа:

Vector3 DirectionRay = transform.TransformDirection(Vector3.forward);

if(Physics.Raycast(transform.position, DirectionRay,out Hit ,Range))

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

Ну или разные слои…У меня больше нет вариантов.

djon801 16 дек 2014, 20:17

так дело в том что первый не пробивается,лучь в него уперается и дальше не чего не обрабатывает,плюс там дистанция меняется

Может я чтото не понял

RadianTOR 16 дек 2014, 21:15

Из точки столкновения с первым колайдером пусти новый лучь дальше в том же направлении

djon801 17 дек 2014, 11:48

все не то,вообщем переделал немного в проэкте все и получилось масками

Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 20

Предотвратить Raycast при нахождении курсора на UI [Решено]

EchoIT 23 сен 2015, 09:50

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

Вот в чём суть вопроса. Есть луч вида:

И есть новый UI на канвасе вида Screen Space — Overlay. Нужно сделать так, чтобы луч (используется Physics.Raycast) не проходил (читай: не выполняется условие на if (Physics.Raycast )), если курсор находится на любом из элементов UI. Возможно, нужна какая-то проверка или как-то можно сделать через layermask, не вдупляю что-то.

Буду признателен за помощь в разрешении этой задачки.

Последний раз редактировалось EchoIT 24 сен 2015, 07:52, всего редактировалось 1 раз.

M16 23 сен 2015, 17:47

Наверное можно воспользоваться Physics.RaycastAll, затем перебрать все полученные GameObject-ы и на их основе уже решать — прошел луч или нет. Будет ли UI элемент в этом списке — не знаю.

RaycastHit[] hitsList = Physics.RaycastAll(camRay, camRayLength, mask);

for (int i = 0; i

Baluska писал(а):Почему-то при билде на андроид не работает, а для Пк все норм. Никто не знает как решить?

Может ты код покажешь, или нам угадать?

MeshAgent agent = GetComponent ();

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

if (Physics.Raycast(ray, out hit))

Последний раз редактировалось Baluska 15 июл 2021, 16:26, всего редактировалось 1 раз.

Baluska 17 июл 2021, 05:55

Сам решил задачу)

public class InputPlayer : MonoBehaviour

public GraphicRaycaster m_Raycaster; //сюда кидаем canvas, на нем должен висеть компонент GraphicReycaster.

public EventSystem m_EventSystem; //сюда кидаем eventsystem

MeshAgent agent = GetComponent ();

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

m_PointerEventData = new PointerEventData(m_EventSystem);

List results = new List ();

if (results.Count == 0)

if (Physics.Raycast(ray, out hit))

Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 10

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

Функциональность моего контроллера платформы для прыжка вниз работает следующим образом:

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

Я попытался сделать метод прыжка вниз, который создает новый raycast из центра коллайдера бокса персонажа (который не показан в приведенном ниже коде, так как я пока что был полностью неудачным) и проверяет наличие столкновения на определенном расстоянии . Моя проблема в том, что он всегда обнаруживает коллайдер платформы, с которой он собирается спрыгнуть, и никогда не имеет возможности обнаружить что-либо еще.

Как мне заставить этот новый raycast игнорировать первое столкновение, потенциально обнаруживать столкновение на расстоянии луча, и если он что-то попадает, позволить моему персонажу спрыгнуть вниз? Кроме того, мне вообще нужно делать новый raycast, или я могу просто использовать текущие raycast на моем контроллере?

Вот фрагмент моего сценария контроллера raycast, который, надеюсь, объясняет некоторые функции:

Physics.Raycast

Успех!

Благодарим вас за то, что вы помогаете нам улучшить качество документации по Unity. Однако, мы не можем принять любой перевод. Мы проверяем каждый предложенный вами вариант перевода и принимаем его только если он соответствует оригиналу.

Ошибка внесения изменений

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

Ваше имя Адрес вашей электронной почты Предложение*

Параметры

originThe starting point of the ray in world coordinates.
direction@param ray Начальная точка и направление луча.
maxDistanceThe max distance the ray should check for collisions.
layerMaskA Layer mask that is used to selectively Colliders when casting a ray.
queryTriggerInteractionSpecifies whether this query should hit Triggers.

Возврат значений

bool @return True если луч пересекся хотя-бы с одним коллайдером,в ином случае — false.

Описание

Casts a ray, from point origin, in direction direction, of length maxDistance, against all colliders in the scene.

You may optionally provide a LayerMask, to filter out any Colliders you aren’t interested in generating collisions with.

Specifying queryTriggerInteraction allows you to control whether or not Trigger colliders generate a hit, or whether to use the global Physics.queriesHitTriggers setting.

This example creates a simple Raycast, projecting forwards from the position of the object’s current position, extending for 10 units.

Notes: Raycasts will not detect Colliders for which the Raycast origin is inside the Collider.

If you move Colliders from scripting or by animation, you need to allow at least one FixedUp to be executed so that the physics library can up before a Raycast will hit the Collider at its new position.

Параметры

originThe starting point of the ray in world coordinates.
direction@param ray Начальная точка и направление луча.
hitIf true is returned, hit will contain more rmation where the collider was hit (See Also: RaycastHit).
maxDistanceThe max distance the ray should check for collisions.
layerMaskA Layer mask that is used to selectively colliders when casting a ray.
queryTriggerInteractionSpecifies whether this query should hit Triggers.

Возврат значений

bool @return True если луч пересекся хотя-бы с одним коллайдером,в ином случае — false.

Описание

Casts a ray against all colliders in the scene and returns detailed rmation on what was hit.

This example reports the distance between the current object and the reported Collider:

This example re-duces the maxDistance parameter to limit how far a to cast the Ray:

Параметры

ray@param ray Начальная точка и направление луча.
maxDistanceThe max distance the ray should check for collisions.
layerMaskA Layer mask that is used to selectively colliders when casting a ray.
queryTriggerInteractionSpecifies whether this query should hit Triggers.

Возврат значений

bool @return True если луч пересекся хотя-бы с одним коллайдером,в ином случае — false.

Описание

Same as above using ray.origin and ray.direction instead of origin and direction.

Параметры

ray@param ray Начальная точка и направление луча.
hitIf true is returned, hit will contain more rmation where the collider was hit (See Also: RaycastHit).
maxDistanceThe max distance the ray should check for collisions.
layerMaskA Layer mask that is used to selectively colliders when casting a ray.
queryTriggerInteractionSpecifies whether this query should hit Triggers.

Возврат значений

bool @return True если луч пересекся хотя-бы с одним коллайдером,в ином случае — false.

Описание

Same as above using ray.origin and ray.direction instead of origin and direction.

This example draws a line along the length of the Ray whenever a collision is detected:

Читайте также: