Как проверить соприкосновение?
Есть два объекта (летящий снаряд и противник), у обоих есть коллайдер, движение происходит и снаряд пролетает сквозь противника, вопрос как определить что снаряд столкнулся?
Я посмотрел примеры и там указывается следующее
void OnCollisionEnter(Collision v)< Debug.Log("tag=>" + v.gameObject.name); if(v.gameObject.name==". ") . >
Это я помещаю в префаб снаряда.
То есть теоретически когда снаряд столкнется с противником должен появится лог с его именем, но ничего нет..
- Вопрос задан более трёх лет назад
- 1848 просмотров
Комментировать
Решения вопроса 1
Griboks @Griboks Куратор тега Unity
Вы точно прочитали документацию и правильно настроили колайдеры? Если нет, то вот вам и ответ. Если да, то, возможно, вам надо поменять метод проверки коллизий на постоянный.
Ответ написан более трёх лет назад
Нравится 1 10 комментариев
Zimaell @Zimaell Автор вопроса
снаряд это куб превращенный в прямоугольник, противник сфера, коллайдеры используются те которые им были выданы при их создании, так же снаряду установлен триггер, что я мог неправильно установить?
Zimaell @Zimaell Автор вопроса
заменил на OnTriggerEnter, работает.
Zimaell @Zimaell Автор вопроса
Не совсем так работает как хотелось бы, при быстром полете видно что снаряд пролетает мимо и тем самым не соприкасается, видно по кадрам что снаряд не касается противника, если конечно сделать медленнее полет то касается, как быть то?
Griboks @Griboks Куратор тега Unity
Zimaell, стандартный метод проверки коллизии — покадровый. Иными словами, в кадре i снаряд не долетел, а в кадре i+1 — уже перелетел. Поэтому необходимо использовать постоянную проверку столкновения.
Zimaell @Zimaell Автор вопроса
то есть все же не через OnTriggerEnter нужно а через OnCollisionEnter?
но так у меня не работает вообще.
Griboks @Griboks Куратор тега Unity
Zimaell, вы точно прочитали документацию?
Zimaell @Zimaell Автор вопроса
Griboks, не понял, еще дополнительно движки физики нужно устанавливать ли я что-то не так понял?
Можете сказать что не так?
Griboks @Griboks Куратор тега Unity
Zimaell, предлагаю вам всё-таки прочитать документацию, чтобы найти ответы на интересующие вас вопросы. Например, в первом абзаце написано:
Unity provides different physics engine implementations which you can use according to your Project needs: 3D, 2D, object-oriented, or data-oriented.
Это означает, что физические движки уже встроены в юнити, и вам не требуется их устанавливать отдельно. А в следующих разделах написано, как правильно настраивать колайдеры, и какие события они активируют при столкновении.
Zimaell @Zimaell Автор вопроса
Griboks, Что-то не совсем пойму, по материалам там куча настроек, у меня вот как
Особо и не разгонишься с настройками.
Туториал 1: 2Д игра — ловилка на Юнити (новичок). Часть 1.
Это туториал по Юнити 3Д для новичков. На самом деле на Ютубе можно найти довольно много видео-туториалов. Но в своем большинстве они показались для меня не особо эффективными. Было не так много туториалов, которые я действительно понимал без знания основ Юнити. Здесь я буду делать относительные простые туториалы в текстовой форме. На самом деле одна из моих целей это поучить английский язык, поэтому эти туториалы обратный перевод с моих туториалов на английском языке. Первый туториал будет о игре — ловилке в 2Д. Для простоты используется встроенная в Юнити физика Physic2D. Надеюсь, что Юнити уже установлена у вас. В туториалах на то время я использовал версию 5.3.5. На тот момент это была последняя стабильная версия. Я обновил скачиваемый пакет до версии 5.5.1. Некоторые скриншоты будут выглядеть немножко по другому, но это не особо критично. Также советую использовать для обучения актуальную версию Юнити.
Понадобится несколько картинок для туториала. Я набросал заготовку в пэинте. Скачать можно тут.*
*возможно некотрые браузеры просто откроют картинку вместо скачивания, сделайте правый клик на картинку и выберите сохранить. Или правый клик на линке и выбрать сохранить цель.
1. Шаг
— Запускаете Юнити. В стартовом окошке выбираете New
— Даёте название проекту
— Выбираете локацию для записи
— Выбираете 2D
— Нажимаете Create Project
Через некоторое время откроется редактор. Важные части для нас будут:
1. Сцена окно, где будет делаться игровая сцена
2. Камера эта область показывает видимую область сцены через камеру
3. Иерархия окно со списком игровых объектов в сцене
4. Инспектор настройка выбранного игрового объекта
5. Проект корневая система папок
6. Ассеты папки, модели, звуки, спрайты, скрипты и тд., то из чего делаете игру
7. Сцена ярлык окошка сцены
8. Игра ярлык игровой камеры
9. Play/Pause/StepPlay кнопки запуска и остановки игры
Вид редактораа можно настроить по своему вкусу. Я пока оставлю стандартный вид.
2. Шаг
Для игры понадобится 4 картинки («земля», «сачок», «плохой предмет», «хороший предмет»).
1. Возможность
Как я уже и говорил, можете скачать мою картинку( Картинка). Надо будет импортировать картинку в Юнити. Правый клик Assets и выбираете Import New Asset... Идете в папку куда скачали картинку, выбираете её catch2DImage и нажимаете Import.
Картинка должна появится в окошке Assets. Но нам надо 4 картинки для этого туториала («земля», «сачок», «плохой предмет», «хороший предмет»). Мы можем указать Юнити, что это multiple (многочисленная) картинка и мы сможем выделить с неё 4 картинки. Выберите catch2DImage в Assets. Потом идете в Inspector и ставите Sprite Mode на Multiple. Кликаете на Apply.
Теперь можно выделить 4 нужные картинки. Картинка должна быть выделенна. Идете опять в Inspector и кликаете на Sprite Editor.
Откроется новое окошко Sprite Editor. Кликаете на Slice. Оставляете все как стоит и кликаете на Slice кнопку. Кликаете на Apply.Над каждой картинкой должен появится четырехугольник. Временами приходится поправить его размер. Закрываете окошко Sprite Editor.
Теперь можно развернуть картинку в Assets. Если все получилось, то вы должны увидеть 4 картинки в развернутом виде.
2. Возможность
Можно использовать и свои картинки. Просто импортируете 4 своих картинки в Юнити. Правый клик в окошко Assets и выбираете Import New Asset... Идёте в вашу папку, выбираете нужные картинки и нажимаете Import.
3. Возможность
Другой путь для импорта объектов в Юнити это просто перетаскивание файлов (drag&drop) в окошко Assets.
3. Шаг
Сделаем землю для игры. Кликаете на картинку земли (это зеленый квадратик по задумке) и перетаскиваете её в Scene. Проверьте, что rectangle tool включен и растяните картинку по сцене (левый клик на края и тяните их). Выберите в окошке Hierarchy catch2DImage_2 правй клик на неё и смените (rename) имя на Ground. Идите в Inspector и измените Order in Layer на 100.
Order in Layer:
Order in Layer важен для отрисовки. Картинки с большим Order in Layer рисуются сверху картинок с меньшим Order in Layer. Это число может быть и негативное, тогда 0 будет сверху -1, -10, .
Нажимаете Play старта сцены. Нажимаете Play повторно для возвращения назад к Scene.
Пока у нас просто одна картинка в сцене. Мы видим её, но другие GameObjects (игровые объекты) не могут взаимодействовать с ней. Нам надо добавить физический компонент (physics2D) Box Collider2D к ней. Выберите Ground в Hierarchy, идите в Inspector. Нажмите на Add Component -> Physics2D -> Box Collider 2D. Наш Ground может теперь взаимодействовать с другими Collider 2D в игровом мире.
Collider:
Collider это физическое тело для игрового объекта. Смотрите тут Unity Manual для подробностей.
4. Шаг
Теперь сделаем игрока (сачок). Большинство шагов совпадает с созданием Ground.
— Добавьте сачок в сцену (перетащите картинку сачка из Assets в Scene)
— Настройте размер (убедитесь, что rectangle tool включен (иконка слева наверху: слева от Pivot))
— Выберите сачок в Hierarchy и назовите его как Player (правый клик и rename)
— Перейдите в Inspector (Player должен быть выделен) и добавьте Box Collider 2D (кликните на Add Component)
— Наш Player будет двигаться. Ему надо дополнительный 2Д-физический компонент Rigidbody2D.
Rigidbody:
Физический движок Юнити может контролировать GameObjects с Rigidbodies. Rigidbodies нужны для физических вычислений. Смотрите Unity Manual для подробностей.
— Перейдите в Inspector от Player и добавьте Rigidbody 2D (кликните на Add Component -> Physics 2D -> Rigidbody2D). Поставьте Interpolate на Interpolate (для плавного движения).
— В Inspector от Player измените Tag на Player.
Tag:
Tag используется для идентификации GameObject. Юнити работает с Tag быстрее чем с именем. Смотрите Unity Manual для информации.
— Order in Layer можно оставить равным 0.
Запустите сцену. сачок должен начать падать и потом остановиться на земле. Нажмите на старт повторно и вернитесь к сцене.
Наш Player должен двигаться налево и направо. Вариантов реализации очень много. Я просто буду менять Velocity (скорость) Player в Rigibody2D. Нам понадобится немножко C# кода. Правый клик на окошко Assets. Выберите: Create -> C# script. Назовите этот скрипт playerMove. Будьте внимательны с названиями (большие и маленькие буквы различаются).
В окошке Assets будет теперь 2 файла (ну или больше, если используете свои картинки).
Откройте playerMove C# скрипт (двойной клик, или правый клик и выбрать open). Откроется C# редактор. Там будет уже стоять заготовка для вашего скрипта. Выглядит примерно так:
Может быть небольшая разница в стиле, если используется другой редактор. Это не важно.
void Start () <> : эта функция выполняется один раз при старте скрипта. Смотрите Unity Manual для информации.
void Update () <> : эта функция выполняется каждый новый кадр. Смотрите Unity Manual .
void FixedUpdate () <> : выполняется через определенный интервал. Используется в основном для вычислений физики. Стандартный интервал 0.02 сек. Check Unity Manual .
В Юнити есть Input Manager, который помогает контролировать ввод пользователя. Можете посмотреть настройки Input Manager: Edit -> Project Setting -> Input. Потом смотрите на окошко Inspector. Пока ничего не меняйте в нем.
Input Manager:
Кратко о принципе работы Input Manager. Например: Horizontal ось. Если пользователь нажимает left(левый курсор) или A кнопку, то значение этой оси меняется на -1. Если нажимается right или D кнопка, тогда значение оси будет 1. если эти кнопки не нажаты, то значение будет 0. На самом деле это не совсем точно, значение меняется между -1 and 1. С джойстиком это было бы нагляднее, но клавиатура либо нажата либо нет. И через скрипт мы можем получить значение этой оси из Input Managerа. Смотрите Unity Manual для инфо.
Теперь мы можем получить три значения из Input Manager (-1 or 0 or 1), в зависимости от нажатых кнопок. И в зависимости от полученного значения из Input Manager мы можем менять velocity (скорость) нашего Player в его Rigidbody2D.
Velocity:
Краткий обзор velocity в Юнити. Velocity это вектор. По значению этого вектора мы видим скорость и направление Rigidbody игрового объекта. Мы можем написать 3Д вектор как (x, y, z). Если объект не двигается, то его velocity равна (0,0,0). Если velocity (-5, 0, 0) то GameObject двигается налево со скоростью 5, с velocity (1, 0, 0) двигается направо со скоростью 1, с velocity (0, 2, 0) двигается наверх со скоростью 2. Юнити это 3Д движок, поэтому не забываем о Z-направлении. Позитивная Z это вперед (в 2Д режиме удаление от нас), негативная Z — приближение. Z-направление не нужно в этом туториале (но не забывайте о Z — оси. Если вы поместите GameObject позади от Camera, то вы не сможете его увидеть в Camera View) при игре. Смотрите Unity Manual для инфо.
Теперь можем сделать C# скрипт для движения. Надеюсь вы знакомы с основой С#.
— Нам нужна float переменная для скорости. Сделайте её public, так у нас будет доступ к ней через Inspector и сможем выставлять её значение не открывая скрипт. Ещё понадобится float переменная значения Horizontal оси. И переменная Vector2 установки скорости и направления движения в Rigibody2D.
public float speed;
float x;
Vector2 move;
— Мы будем изменять velocity в Rigidbody2D. Поэтому нам нужна переменная для компонента Rigidbody2D.
Rigidbody2D rb;
— Теперь мы можем сделать ссылку rb переменной на Rigidbody2D. Это надо будет сделать только один раз. С помощью GetComponent < Name >(); мы получаем доступ к Component от GameObject. Такая ссылка конечно не обязательна, но что бы не писать каждый раз GetComponent < Rigidbody2D >(); когда нам нужен доступ, мы просто заменяем эту команду на линк через переменную rb.
void Start () <
rb = GetComponent < Rigidbody2D >();
>
Для измений в Rigidbody2D лучше использовать FixedUpdate. Так как физика считается через определенные интервалы, то нет смысла менять её каждый кадр. Смотрите Unity Manual для деталей. Мы будем получать значение Horizontal оси на каждом шаге вычисления физики (доступ к Input Manager довольно прост, используйте команду Input.). Потом мы посчитаем вектор направления и скорости в зависимости от значения оси Horizontal и переменной speed (пара слов о rb.velocity.y. мы будем заменять векторную часть скорости по оси-Y (вверх-вниз) на неё же саму при просчете нового вектора rb.velocity. Это делается только для того, что бы исключить наше влияние на движение по Y-оси. Тогда наш сачок сможет например и дальше падать под действием гравитации, хотя мы и будем менять вектор движения по оси-Х. Мы не должны менять этот вектор на (x, 0) или наш сачок Player будет зависать в воздухе при движении налево или направо. В конце мы подменим вектор движения velocity у Player на посчитанный вектор.
void FixedUpdate () <
x = Input .GetAxis ( «Horizontal» );
move = new Vector2 (x * speed, rb.velocity.y);
rb.velocity = move;
>
В итоге получился такой скрипт:
Забудьте пока о копировании и вставке. Набирайте текст вначале вручную. Будет видно как редактор будет подсказывать возможные варианты при наборе. И пустая функция Update() пока не нужна нам, поэтому я её удалил.
using UnityEngine;
using System.Collections;
public class playerMove : MonoBehaviour
//видимая из редактора Юнити, float переменная для скорости (лево/право) Player
public float speed;
//переменная для ссылки на компонент Rigibody2D от Player
Rigidbody2D rb;
//float переменная для оси Horizontal из Input Manager
float x;
//Vector2 переменная для просчитанного вектора движения, используется для изменения velocity
Vector2 move;
//функция выполняется 1 раз при старте скрипта
void Start () <
//делаем линк на Rigidbody2D компонент
rb = GetComponent < Rigidbody2D >();
>
//функция выполняется с определенным интервалом (по умолчанию 0.02)
void FixedUpdate () <
//считываем значение оси из Input Manager и записываем его в переменную
x = Input .GetAxis ( «Horizontal» );
//высчитываем новый вектор движения (меням х, у оставляем прежней)
move = new Vector2 (x * speed, rb.velocity.y);
//меняем вектор движения
rb.velocity = move;
>
>
Теперь добавьте этот скрипт к Player. Выделите Player в Hierarchy окошке. Кликните на Add Component в Inspector -> Scripts -> Player Move.
(как альтернатива: можете выделить Player в Hierarchy окошке и потом просто перетащить скрипт на окошко Inspector)
Выберите Player в Hierarchy, перейдите к Inspector и измените переменную speed в скрипте Player Move на 5 (это скорость движения).
Запустите сцену через Play и попробуйте подвигать сачок с помощью a-d или left — right кнопок. Вернитесь назад в Scene (нажмите Play повторно)
5. Шаг
Нам нужны предметы для поимки. Сделаем сначала один «Good»(хороший) GameObject (игровой объект). Возмите рыбу картинку для этого. Перетащите рыбу картинку в Scene.
— Выделите её в Hierarchy. Измените имя на Fish.
— Перейдите в Inspector и измените Tag на Good (кликните на untagged -> Add New Tag -> Добавьте новый tag Good -> Вернитесь (выберите (если сбросилось выделение) Fish в Hierarchy -> измените untagged на Good. В последствии мы будем использовать этот тэг для проверки соприкосновений.
— Измените Order in Layer на -10. Так этот GameObject будет отрисовываться позади тех, что сейчас находятся в сцене (у нас Ground = 100, Player = 0).
— Добавьте Rigidbody 2D (Add component -> Physics 2D -> Rigidbody 2D). Поставьте Gravity Scale на 0.1. Так уменьшаем скорость падения.
— Поставьте Interpolate на Interpolate (для плавности движения).
— Добавьте Box Collider 2D. Включите галочку Is Trigger.
Collider is Trigger:
Trigger-Collider это похоже на режим призрака для GameObject. Trigger-Collider будет проходить через другие Collider. Но мы сможем регистрировать и обрабатывать эти соприкосновения. Потом мы будем проверять коснулся-ли Player другого падающего объекта (например Fish). Смотрите Unity Manual для деталей.
В игре мы будем спавнить (это наверно довольно общепринятый сленг, то есть помещать в сцену) эти объекты Fish. Если Fish не был пойман, то этот объект провалится через пол и будет дальше падать. Мы этого не будем видеть, но Юнити продолжит заниматься их вычислением. Поэтому нам лучше удалить эти объекты из сцены. Мы просто можем удалять их по времени (например через 5 секунд). Сделаем небольшой скрипт для этого.
Создайте C# script в Assets (правый клик Assets -> Create -> C# Script). Назовите его timeDestroyer. Откройте его (двойной клик или правый клик и -> Open).
Нам нужна float переменная для продолжительности жизни объекта (public что бы настраивать через Inspector).
public float aliveTimer;
Нам нужна функция удаления GameObject из Scene. GameObject может быть уничтожен с помощью Destroy(gameObject, time); (gameObject это краткая ссылка на тот GameObject, где находится скрипт. Time это задержка в секундах прежде чем GameObject будет уничтожен). Мы можем добавить эту функцию в Start (). Теперь если Fish будет заспавнен, то запустится функция Destroy которая отсчитает заданное время и уничтожит GameObject.
void Start () <
Destroy (gameObject, aliveTimer);
>
Наш скрипт уничтожения получится такой:
using UnityEngine;
using System.Collections;
public class timeDestroyer : MonoBehaviour
//время жизни объекта
public float aliveTimer;
//исполняется 1 раз при запуске скрипта
void Start () <
//уничтожит текущий объект через заданное время
Destroy (gameObject, aliveTimer);
>
>
Выделите Fish в Hierarchy. Перейдите в Inspector и добавьте timeDestroyer скрипт. Поменяйте Alive Timer на 5.
Пока у нас только один объект Fish в Scene. Позже нам понадобится большее количество. Мы можем сделать заготовку для клонирования Fish. В Юнити для этого используется Prefab.
Prefab:
Prefab используется как образец для клонирования. Можно сделать Prefab из любого GameObject. И потом просто использовать клоны по мере необходимости. Prefab не зависит от клонов. Мы можем изменять или уничтожать клоны не портя при этом сам образец. Смотрите Unity Manual для подробностей.
Создать Prefab очень просто. Выберите Fish в Hierarchy и просто перетащите его в Assets. Юнити автоматически создаст Prefab (или правый клик в Assets окошко -> Create -> Prefab, назовите его и перетащите Fish на него).
6. Шаг
Теперь нам нужен Bad (плохой) объект, поимку которого надо избегать. В целом этот объект будет похож на Fish. Только его Tag и картинка будут отличаться (возможно размер коллайдера). Так что просто слегка изменим Fish. Надеюсь вы сделали Prefab от Fish. Выберите Fish в Hierarchie окошке.
— Смените его название на Bomb (правый клик -> Rename)
— Перейдите в Inspector и смените его Tag на Bad (принцип как и с тэгом Good, смотрите шаг 5. untagged -> add new tag -> +)
— Смените картинку на бомбу (выделите Bomb в Hierarchy, перетащите картинку бомбы из окошка Assets в поле Sprite в компоненте Sprite Renderer в Inspector (или нажмите кружок справа от поля Sprite и выберите картинку бомбы)).
— Поправьте размер Collider2D под новую картинку (нажмите Edit Collider в Inspector).
— Сделайте prefab от bomb (выберите Bomb в Hierarchy и перетащите объект в Assets).
После того как сделали Prefab от Bomb, выделите Bomb в Hierarchy и удалите этот объект.
7. Шаг
Теперь сделаем спавнер (есть такое слово ? «рожалку»). Предметы будут спавниться сверху от Camera. Сделаем границы для спавна. Добавьте пустой GameObject. Нажмите кнопку наверху GameObject -> Create -> Empty. У нас появится Empty GameObject в сцене. Выделите этот GameObject и назовите его Spawner (правый-клик -> Rename). Перейдите в Inspector и сделайте ему иконку для лучше видимости в сцене (смотрите скриншот). Измените Z-position на 0 (если отличалось от 0). Выберите moving tool и передвиньте Spawner на левую сторону от камеры Camera. Мы будем использовать эту позицию для границы спавна. Сделайте дубликат от Spawner. Правый клик на него и выберите Duplicate. Передвиньте дубликат на правую сторону. Смените имя на RightSide. Смотрите скриншот для подробностей.
Теперь можно сделать скрипт для спавна. Создайте новый C# script (правый клик в Assets -> Create -> C# Script) назовите его ItemSpawn. Откройте его. Краткий принцип его работы: у нас будет массив со спавнящимися предметами (пока у нас есть заготовки Fish и Bomb). Периодично мы будем спавнить один случайный предмет из этого массива. Позиция для спавна тоже будет выбранна случайно между границами для спавна. Для границ используем позиции Spawner и RightSide.
Нам нужна переменная для игрового объекта RightSide (мы сможем получить нужную позицию Transform для спавна с этого объекта).
public GameObject RightSide;
Массив для списка падающих предметов. Сделаем его публичным, что бы заполнить через Inspector. Fish и Bomb будут членами этого массива.
public GameObject [] items;
Float переменные для первоначальной задержки спавна и его периодичности.
public float startDelay, repeatRate;
Нам нужна функция для переодичного запуска спавна. Вариантов реализации как обычно много. Я буду использовать функцию InvokeRepeating («name», startDelay, repeatRate), где name название функции спавна. Эта функция запускается один раз в Start (); и потом она автоматически периодично вызывает функцию спавна.
void Start () <
InvokeRepeating ( «Spawn» , startDelay, repeatRate);
>
Теперь к функции Spawn. Для начала посчитаем случайную позицию для спавна. Позиция это 3Д вектор. Для Х-части мы возьмем случайное значение между Spawner и RightSide. Для Y-части мы просто возмем Y-значение от Spawner (оно не будет меняться). И Z-значение будет 0.
2Д и Z-ось:
Не забывайте о Z-позиции в 2Д играх. Юнити 3Д движок, если что-то поместите за Camera,то она не сможет отобразить этот объект. По умолчанию Z-позиция у камеры -10.
Vector3 pos = new Vector3 ( Random .Range (gameObject.transform.position.x, RightSide.transform.position.x), gameObject.transform.position.y, 0 );
Transform:
Небольшое отступление о Transform компоненте. Помните о доступе к компонентам через GetComponent < Name >();? Transform компонент это исключение. Так как этот компонент в обязательном порядке есть у любого игрового объекта, то есть упрощённый путь доступа к нему. Просто используйте gameObject.transform.» и потом уже переходите к его частям .position или .rotation. gameObject указывает на текущий объект (там где скрипт), а transform это прямой доступ к его Transform компоненту.
Теперь у нас есть случайная позиция для спавна. Спавн объекта в Юнити можно сделать через функцию Instantiate (gameobject, position, rotation). Мы выберем случайный объект из массива (item.length это длина массива. Нам не обязательно самим считать его размер. И впоследствии можно будет добавитть новые объекты к массиву без поломки скрипта). Позиция у нас уже высчитана. И ротация будет как у объекта Spawner(то-есть никакой ротации).
Instantiate (items [ Random .Range ( 0 , items.Length)], pos, gameObject.transform.rotation);
Скрипт спавна пока получается такой:
using UnityEngine;
using System.Collections;
public class ItemSpawn : MonoBehaviour
//объект, из которого мы будем считать правую границу спавна
public GameObject RightSide;
//массив с объектами для спавна
public GameObject [] items;
//float переменные: задержка первого спавна и его период
public float startDelay, repeatRate;
//выполняется 1 раз при старте
void Start () //запуск периодического выполнения спавна
InvokeRepeating ( «Spawn» , startDelay, repeatRate);
>
//функция спавна
void Spawn () //рандомная X-позиция между Spawn и RightSide
Vector3 pos = new Vector3 ( Random .Range (gameObject.transform.position.x, RightSide.transform.position.x), gameObject.transform.position.y, 0 );
//спавн случайного предмета на посчитанной позиции
Instantiate (items [ Random .Range ( 0 , items.Length)], pos, gameObject.transform.rotation);
>
>
Выделите Spawner в Hierarchy. Добавьте скрипт спавна к нему. Перетащите RightSide из Hierarchy на RightSideполе в скрипте. Разверните массив для предметов (кликните на Items). Заполните его образцами предметов (переташите Fish и Bomb из Assets на Items). Размер массива должен стать 2. Измените delay и rate на 2 каждую (можете настроить потом по желанию).
Можете запустить сцену для теста.
8. Step
Теперь нужен скрипт для поимки предметов. С помощью 2Д физики мы можем регистрировать соприкосновения объектов с 2Д коллайдерами. У Bomb и Fish есть Trigger Collider2D. Для регистрации можем использовать OnTriggerEnter2D ().
OnTrigger. вызовы:
OnTriggerEnter2D () — запускается если collider2D попал в триггер
OnTriggerStay2D () — will be started if collider2D находится в триггере несколько кадров
OnTriggerExit2D () — will be started if collider2D вышел из триггера
Смотрите Unity Manual для деталей.
Создайте новый C# script (правый клик в Assets). Назовите его itemChecker. Откройте его.
Нам нужна переменная для учета очков.
public int score;
У OnTriggerEnter2D есть параметр Collider2D. Мы можем проверить какой GameObject попал в триггер. Так есть GameObject, мы можем проверить его Tag. Если это Good предмет, то мы увеличим очки. Если это плохой Bad предмет, то уменьшим их. Потом мы можем уничтожить предмет попавший в сачок.
void OnTriggerEnter2D ( Collider2D other) <
if (other.gameObject.tag == «Good» ) score = score + 10 ;
Destroy (other.gameObject);
>
if (other.gameObject.tag == «Bad» ) score = score — 10 ;
Destroy (other.gameObject);
>
>
Наш itemChecker скрипт будет такой:
using UnityEngine;
using System.Collections;
public class itemChecker : MonoBehaviour
//переменная для результата
public int score;
//запустится при попадании объекта с Collider2D в Trigger
void OnTriggerEnter2D ( Collider2D other) <
//проверка Tag предмета, это Good ?
if (other.gameObject.tag == «Good» ) //увеличить результат, если да
score = score + 10 ;
//удалить предмет попавший в триггер
Destroy (other.gameObject);
>
//проверка Tag предмета, это Bad ?
if (other.gameObject.tag == «Bad» ) //уменьшить результат, если да
score = score — 10 ;
//удалить предмет попавший в триггер
Destroy (other.gameObject);
>
>
>
Выделите Player в Hierarchy. Добавьте itemChecker к нему в Inspector.
Сохраните сцену как catchGame. Выделите Player и запустите сцену. Вы должны увидеть как меняется Score (в Inspector у Player).
Основа игры готова. Смотрите Вторую часть для продолжения.
скачать готовый проект этого туториала.
нет столкновения с машиной и объект не уничтожается.
Добрый день, друзья! Подскажите, пожалуйста. Сделал простейшую аркаду, но у меня почему-то сама машинка при соприкосновении с другими машинками проходит сквозь них, хотя у всех машин установлено свойств Box collider2d. А также я запрограммировал уничтожение машинки при соприкосновении по тэгу с другими машинки, но почему -то машинка не уничтожается. Тэги проверил, стоят. Можете помочь, в чем проблема? Здесь фото экрана https://disk.yandex.ru/i/8CaUax11esS3zw. А здесь проект https://disk.yandex.ru/i/8CaUax11esS3zw
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
<
public float speed = 3f;
void Update()
<
float hor = Input.GetAxisRaw(«Horizontal»);// Получение координаты при нажатии на клавишу по оси икс
Vector3 dir = new Vector3(hor, 0, 0);
transform.Translate(dir.normalized * Time.deltaTime * speed);// перемещение самой машинки на вычисленную ранее координату
>
private void OnCollisionStay(Collision collision)
<
if (collision.gameObject.CompareTag(«car»))// если просиходит столкновение с другими авто с тэгом car, то объект уничтожается.
Destroy(gameObject);
>
>
#1
14:18, 31 июля 2022
При использовании физики нужно добавлять rigidbody, если управляется напрямую с помощью скриптов, то установить в режим kinematic.
Перемещать исключительно влияя на rigidbody, а не transform.
Если не требуется физических столкновений, коллайдер перевести в режим trigger.
Использовать OnCollisionEnter (OnTriggerEnter в случае триггера), вместо OnCollisionStay.
- Eugeny1984
- Пользователь
#2
14:40, 31 июля 2022
Tokarn
> OnTriggerEnter
поставил параметр Body Type =Cinematic. — не помогло. Перемещать исключительно влияя на rigidbody, а не transform. -это как? Пробовал галочку ставить на is Trigger — не помогло.
#3
14:53, 31 июля 2022
transform.position это телепорт объекта, так физические тела не двигают. И да на всех машинах должен висеть rigidbody. Trigger не используется для физических коллизий, он служит для обнаружения вхождения в него другого физического тела.
Найди физическое тело автомобиля
Rigidbody Telo = AutoObject.transform.GetComponent();
Задай ему импульс
Telo.AddForce(transform.forward * 7f * Time.deltaTime * 1000f, ForceMode.Impulse);
#4
16:42, 31 июля 2022
Eugeny1984
> поставил параметр Body Type =Cinematic. — не помогло. Перемещать исключительно
> влияя на rigidbody, а не transform. -это как? Пробовал галочку ставить на is
> Trigger — не помогло.
1) На всех физических объектах в игре, не являющихся статичными должен присутствовать Rigidbody
Почему:
а) При отсутствии rigidbody объект с коллайдером считается статичным и входит в массив статичных коллайдеров.
б) Массив статичных коллайдеров создан чтобы обрабатывать все взаимодействие со статикой в физическом движке за один присест, т.е. очень оптимизированно.
в) При изменении любого элемента в массиве статичных коллайдеров ведется полный перерасчет всех объектов являющихся статичными (объекты с коллайдером без rigidbody или с rigidbody в состоянии «Static»), что занимает большое количество вычислительной мощности, если таких объектов очень много.
2) Физические игровые объекты (т.е. с rigidbody), полностью управляющиеся с помощью скрипта-контроллера или например анимации (например платформа анимированная в Аниматоре) или агента NavMesh, должны быть переключены в состояние «Kinematic»
Почему:
а) При состоянии не равном Kinematic, состояние может быть либо Static, либо Dynamic: в первом случае оно относится к статическим объектам и его положение не должно изменяться вообще, дабы избежать просадок в производительности (как стена, которую не возможно сдвинуть и сломать), во втором случае положение объекта управляется физическим движком (с физически правильным просчетом столновений, силой тяжести и т.п., как шарик в пинболе).
б) Использование статического ригидбоди все равно что не использовать ригидбоди вообще. Любой объект с коллайдером но без компонента Rigidbody считается движком статическим физическим объектом, т.е. по умолчанию объект с коллайдером без ригидбоди получает свойства как у объекта с ригидбоди в состоянии Static.
в) В случае Dynamic передвижением можно управлять добавляя силу (AddForce) в нужном векторе (например персонаж в платформере, бегает и прыгает — в части случаев это rigidbody в режиме dynamic, с фиксированным углом поворота).
г) В твоем случае это Kinematic с полным контролем движения через скрипт, ты напрямую управляешь положением физического тела. Например в твоем случае можно указать ригидбоди в инспекторе: public Rigidbody rb; А затем использовать её rb.position += dir.normalized * Time.deltaTime * speed;
3) Если в твоей игре требуется только коснуться с объектом и он удаляется, производительнее использовать триггер-коллайдеры, вместо обычных коллайдеров.
Почему:
а) Событие коллизии двух коллайдеров собирает в себя большое количество не нужной в таком случае информации — векторы столкновений, точка пересечения, расчеты физики столкновений и т.п. Событие пересечения коллайдеров «легковеснее» для расчетов. Например для пуль в платформере не нужно использовать коллайдеры, если пули не рикошетят с физически правильным просчетом, а сразу исчезают и показывают эффект попадания, вместо этого используются триггер-коллайдеры. Судя по всему у тебя другие машины ведут себя как снаряды, сразу же уничтожаясь при столкновении.
б) Столкновения с другими коллайдерами могут вызвать лишние дерганья, баги, если движение обоих объектов управляются скриптами и один или двое из объектов имеет динамический ригидбоди. Если игрой не предполагаются физически правильные столкновения, а просто имеет место быть «событие столкновения с препятствием», то смысла в использовании коллайдеров в режиме коллизий нет.
4) В расчете столкновения использовать OnCollisionEnter (OnTriggerEnter в случае триггера), вместо OnCollisionStay.
Почему:
а) При использовании OnCollisionStay код срабатывает не в момент первого касания, а чуть позже (в следующем цикле физических расчетов).
б) При использовании OnCollisionStay предполагается что два объекта некоторое время соприкасаются друг с другом, и каждый физический тик выполняется код, указанный в функции OnCollisionStay — т.е. не единожды, а почти каждый кадр или несколько раз в кадр.
в) OnCollisionEnter (OnTriggerEnter) выполнятся именно в момент соприкосновения с другим игровым объектом с коллайдером (триггером в случае OnTriggerEnter), в отличии от OnCollisionStay, что при больших скоростях сделает просчет игровых событий гораздо стабильнее (при очень больших скоростях и расчетах столкновения в OnCollisionStay, пройденное за один физический тик расстояние может значительно влиять на геймплей, вызывая баги).
г) Использование OnCollisionStay можно рассматривать в контексте блока с лавой, когда на нем стоишь тратится здоровье — т.е. выполняется просчет всё время, пока ты касаешься блока. В то время как OnCollisionEnter (OnTriggerEnter) выполняется только в момент первого касания и единожды.
#5
16:53, 31 июля 2022
Eugeny1984
Обращаясь к transform вместо rigidbody ты просто телепортируешь объект полностью без просчета физики, такая методика применима только к объектам не имеющим физического тела (например объект, выполняющий роль какого-то визуального эффекта).
Если перемещать transform объекта с rigidbody, физическое столкновение все равно может быть просчитано движком в следующий физический тик, но вместо логичного легковесного в расчетах и правильного поведения будет использоваться некий физический дебагер, который будет рассчитывать как вытащить один коллайдер, застрявший в другом — это в сотни и тысячи раз тяжелее для расчетов и будет сильно затормаживать систему в случае массовых пересечений коллайдеров.
- Eugeny1984
- Пользователь
#6
18:01, 31 июля 2022
Tokarn
> а) Событие коллизии двух коллайдеров собирает в себя большое количество не
> нужной в таком случае информации — векторы столкновений, точка пересечения,
> расчеты физики столкновений и т.п. Событие пересечения коллайдеров
> «легковеснее» для расчетов. Например для пуль в платформере не нужно
> использовать коллайдеры, если пули не рикошетят с физически правильным
> просчетом, а сразу исчезают и показывают эффект попадания, вместо этого
> используются триггер-коллайдеры. Судя по всему у тебя другие машины ведут себя
> как снаряды, сразу же уничтожаясь при столкновении.
> б) Столкновения с другими коллайдерами могут вызвать лишние дерганья, баги,
> если движение обоих объектов управляются скриптами и один или двое из объектов
> имеет динамический ригидбоди. Если игрой не предполагаются физически правильные
> столкновения, а просто имеет место быть «событие столкновения с препятствием»,
> то смысла в использовании коллайдеров в режиме коллизий нет.
> 4) В расчете столкновения использовать OnCollisionEnter (OnTriggerEnter в
> случае триггера), вместо OnCollisionStay.
> Почему:
Спасибо за подробности, но из того, что вы написали, я понял лишь 10%, пробовал использовать OnCollisionEnter — не уничтожается все равно объект при столкновении. вы лучше скажите, пож. как исправит, чтобы столкновения просходили?
#7
18:14, 31 июля 2022
Eugeny1984
Уберите проверку на тег и попробуйте проверить работу скрипта без него, если позволяет механика. Может быть у вас ошибка в написании тега.
- Eugeny1984
- Пользователь
#8
18:38, 31 июля 2022
Tokarn
я закоментировал private void OnCollisionStay(Collision collision), чтобы компилятор не воспринимал. К сожалению все без изменений.
#9
18:43, 31 июля 2022
Eugeny1984
Вы не понимаете базовый синтаксис кода, уделите время изучению простейших примеров кода на C# с подробным разжевыванием каждой строчки.
Лучше будет на примере самых азов разработки на юнити, где уделено внимание скриптингу. Лучше в видео формате.
Это не приведет к быстрому решению вашей задачи, потому что конкретного решения вы не найдете. Оно окупится вам в будущем, спустя недели, когда ваше подсознание переварит полученную информацию и на основе её вы сможете строить новые осознанные и более сложные логические цепочки, включая и решение вашей задачи. Если конечно вы не забросите практику разработки игр.
Если кто-то захочет оказать вам медвежью услугу и предоставить готовый код, это буду не я.
- Eugeny1984
- Пользователь
#10
22:11, 31 июля 2022
Tokarn
На мой взгляд у меня нет в коде ошибок, может быть я конечно ошибаюсь, но вроде как у меня все строчки закоментированы, ошибок никаких не выдает юнити. По мне так это где-то может точки запятой не хватает или еще какой-то мелочи в коде или в физике какая то галочка в свойствах объекта лишняя?
#11
0:29, 1 авг 2022
1) Проверьте не используете ли вы Collider2D и rigidbody2D в связке с методом OnCollisionEnter или аналогичным. В unity используются два физических движка не связанных друг с другом: для 2D физики и для 3D физики. Для 2D физики есть методы-синонимы, например OnCollisionEnter2D и т.д.
2) Проверьте правильно ли указан тег который вы указали для объекта в инспекторе. Теги регистрозависимые, т.е. MainCamera != mainCamera.
3) Проверьте наличие коллайдеров у обоих объектов, которые должны создавать коллизию.
4) Проверьте чтобы используемый метод соответствовал используемому типу коллайдера. Т.е. если коллайдер препятствия отмечен как триггер-коллайдер, а используется метод для отслеживания коллизии между двумя коллайдерами, а не пересечения с триггером, метод отрабатывать не будет. Это же работает в обратную сторону.
- DemiosFantasimo
- Участник
#12
4:38, 1 авг 2022
Когда тебе написали что нужно перемещать через rigibody нужно было начать копаться что такое это самое rigibody. Ты опять берешся за игру не понимая что ты пишешь. Просто берись за свой код, и по порядку бери от туда из того что не понимаешь и штудируй, а то опять будешь плодить вопросы по самым базовым вопросам. Почитай об этом, посмотри видео. Создай пустой проект и на кубах тестируй. Когда дойдет как это работает то уже берись за игру.
- Eugeny1984
- Пользователь
#13
15:37, 1 авг 2022
DemiosFantasimo
Как раз в этот раз я и понимаю ,что написал, здесь код очень простой и закоментирован. Ну не хотите вникать в мою проблему, я вас не заставляю.
#14
15:54, 1 авг 2022
1. тебе уже помогали и не раз
2. но ты спрашиваеш однотипные вопросы
3. никто нехочет ковырять где и какую галочку ты не проставил
4. тебе дают описание как это работает, но ты не особо хочеш это понять
5. ты делаеш свой проект на основе «тыкну тут — вдруг заработает»
Проверка на соприкосновение объекта Unity
Знаете кого-то, кто может ответить? Поделитесь ссылкой на этот вопрос по почте, через Твиттер или Facebook.
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.