Всем привет! Давно ничего не писал, но сейчас захотелось рассказать про очень удобную штуку, о которой многие не знают. Это Event System в Unity. Многие, для задач в которых EventSystem очень удобен, используют обычный Raycast. Я расскажу про то, как пользоваться частью функционала EventSystem (его на самом деле очень много) и как этот инструмент позволяет быстро решать многие задачи связанные с обработкой событий интерфейсов и объектов. Как всегда с репозиторием с примерами. Если вам интересно — добро пожаловать под кат!
В данной статье я разберу и предоставлю примеры работы с событиями IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler, IDragHandler, IBeginDragHandler, IEndDragHandler (полный список событий можно посмотреть тут).
Что же такое EventSystem? EventSystem — это система отвечающая за обработку разных событий в сцене. В основном она позволяет:
- Определять какой GameObject “выбран”
- Управлять способами ввода которые используются
- Управлять рейкастингом
Подробнее всего в данной статье мы разберём третий пункт, так как он самый простой и удобный в использовании.
С точки зрения рейкастов в EventSystem доступны три основных компонента:
- Graphic Raycaster — используется для работы с UI
- Physics 2D Raycaster — используется для взаимодействия с физическими объектами в 2D
- Physics Raycaster — используется для взаимодействия с физическими объектами в 3D
Важная деталь для всех взаимодействий будь то физика или ui необходимо чтобы объект EventSystem присутствовал на сцене.
Начнём с самого простого — с UI системы. С ней EventSystem работает проще всего и лучше всего. Дело в том, что при создании Canvas юнити сразу добавляет на сцену все необходимые компоненты, такие как сам EventSystem и Graphic Raycaster.
В случае с UI, событийная система позволяет легко создавать свои кнопки и базовые взаимодействия с разными UI элементами. Для примера разберём IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler, IDragHandler, IBeginDragHandler, IEndDragHandler.
Чтобы UI элемент реагировал на события входа (IPointerEnterHandler), выхода (IPointerExitHandler) курсора мыши необходимо имплементировать эти интерфейсы в необходимый объект. Это помогает во многих случаях, когда нужно что-то выбрать, подсветить и т.п. На примере с тестовой сценой и Image это позволяет сделать интеракции вроде такой в несколько строк кода:
public void OnPointerEnter(PointerEventData eventData)
{
_Image.color = Color.blue;
}
public void OnPointerExit(PointerEventData eventData)
{
_Image.color = Color.white;
}
Для обработки событий нажатия на UI элемент есть два других интерфейса IPointerDownHandler, IPointerUpHandler.
Их имплементация позволяет в удобном виде обрабатывать события нажатия на объект мышью или тача на мобильных платформах:
public void OnPointerDown(PointerEventData eventData)
{
_Image.color = Color.green;
}
public void OnPointerUp(PointerEventData eventData)
{
_Image.color = Color.red;
}
EventSystem работает с любым компонентом UI системы, который может быть RaycastTarget. Для примера Text и событие клика IPointerClickHandler (важно, это событие похоже на IPointerUpHandler, то есть срабатывает в момент поднятия мыши, но отличие заключается в том, что “отпускание” курсора должно происходить строго в границах объекта):
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class UITextExample : MonoBehaviour, IPointerClickHandler
{
private Text _Text;
private bool _IsClicked;
private void Start ()
{
_Text = GetComponent<Text>();
}
public void OnPointerClick(PointerEventData eventData)
{
_Text.text = _IsClicked ? "Hello there!" : "General Kenobi";
_IsClicked = !_IsClicked;
}
}
Самыми интересными ивентами на мой взгляд, являются те, что позволяют удобно делать Drag. Это набор интерфейсов IDragHandler, IBeginDragHandler, IEndDragHandler. С ними так же всё очень просто. Визуальный эффект сильно зависит от способа обработки, но эти три события позволяют делать самые разные взаймодействия за несколько минут. В случае, если элемент, который вы собираетесь двигать состоит из разных UI элементов, важно отключать галочку RaycastTarget на тех элементах, которые не являются интерактивными. (Важно: в случае с UI системой нужно использовать screenPosition из PointerEventData которая приходит во всех методах событийной системы связанных с мышью/тачем)
public class UIDragExample : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
[SerializeField] private Text _Text;
public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.pointerCurrentRaycast.screenPosition;
}
public void OnBeginDrag(PointerEventData eventData)
{
_Text.text = "You dragging!";
}
public void OnEndDrag(PointerEventData eventData)
{
_Text.text = "Drag me!";
}
}
В общем то по UI системе всё, на самом деле там есть ещё несколько полезных штук с точки зрения Event System, но про них я может напишу в будущих статьях.
Работа с физическими объектами отличается лишь двумя пунктами. Первое — надо внимательно следить, чтобы объект EventSystem был на сцене, чтобы это работало. Второе — надо повесить компонент PhysicsRaycaster на основную камеру, чтобы всё это так же работало по коллайдерам. В остальном почти тоже самое, простенький пример вы можете найти в репозитории.
В общем EventSystem крутой и удобный инструмент, который позволяет многие вещи делать в разы быстрее нежели обычными рейкастами. Кроме того в EventSystem есть очень много полезного функционала вроде того, что там можно переопределять инпуты (к примеру вас интересует специфичный контроллер, скажем Leap Motion) и многое другое, о чём я может напишу в будущих статьях.
Спасибо за внимание!
Автор: DyadichenkoGA