Переключить целевую систему событий - PullRequest
1 голос
/ 05 июня 2019

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

Это позволяет обычным событиям единства запускаться соответствующим образом для соседнего объекта, даже если указатель не можетбыть непосредственно на цели.(Помощь прицела / привязка / стабилизация указателя)

Моя проблема в том, что, хотя я обновляю выбранный игровой объект системы событий с помощью желаемой цели, система событий единства не срабатывает, поскольку все еще считает, что указатель нене над мишенью.(Хотя диалоговое окно отладки системы событий редактора и эффекты «Подсветка» (для элементов пользовательского интерфейса) запускаются соответственно и показывают, что выбранная цель изменилась.)

//Raycast to snapped object
Physics.Raycast(pos, rot, out hitInfo, 20f);
//Populate pointer event data using current
PointerEventData ped = new PointerEventData(EventSystem.current);

//Update data using snapped objects data
ped.pointerCurrentRaycast = new RaycastResult {
   distance = hitInfo.distance,
   gameObject = focusedObject,
   sortingLayer = hitInfo.transform.gameObject.layer,
   worldNormal = hitInfo.normal,
   worldPosition = hitInfo.point
};

//Update current target - Target changes in unity debug dialog, but has no effect on clickability
EventSystem.current.SetSelectedGameObject(focusedObject, ped);

Чего мне не хватает?

- Редактировать для уточнения -

В настоящее время я использую код на основе луча и расстояния, чтобы привязать указатель к цели на компонентах без графического интерфейса пользователя, что позволяет выбирать на основе указателя привязки цели.После того, как цель не-GUI «привязана», я использую ExecuteEvents.ExecuteHierarchy для IPointerEnter / Exit / Down / Up / Click, чтобы вручную инициировать события по мере необходимости.

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

-- Изменить 2 -

Я должен добавить, что я использую HoloLensInputModule Unity и HoloLensInput для обработки взаимодействий пользовательского интерфейса, в то время как использую мои собственные raycasts для обработки компонентов, не относящихся к пользовательскому интерфейсу.

Похоже, что мне нужно будет расширить GetGazeScreenPosition() HoloLensInput.cs с помощью моего кода привязки, чтобы больше не было необходимости обновлять систему событий

- В основном решено -

В основном я решил эту проблему, расширив StandaloneInputModule и BaseInput и переопределив несколько методов во всей их структуре наследования.(Это некрасиво, но работает и работает более эффективно, поскольку я могу отбрасывать нежелательные дополнительные вызовы RaycastAll)

Суть в том, чтобы переопределить не только вызов RaycastAll, скрытый глубоко в унаследованных классах, но итакже каждый раз, когда eventData запрашивается или манипулирует.Большая часть изменений относится к GetMousePointerEventData() и ProcessMouseEvent() и почти ко всем вызовам методов, включенным в цепочку, включая рекурсивные дочерние элементы.

При этом существует проблема с полосами прокрутки, которые переключаются между минимальной и максимальной прокруткой,Похоже, что проблема возникает из-за значения pointerEventData.position, которое внутренне используется ползунком после ProcessDrag()'s ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);

1 Ответ

0 голосов
/ 05 июня 2019

Первая проблема заключается в том, что SetSelectedGameObject не отправляет и не пересылает событие игровому объекту.Это делается для того, чтобы изменить то, что система событий отслеживает как выбранный игровой объект и может отправлять события OnSelect и OnDeselect.

Если вы действительно хотите выполнить событие с определенной целью, вы 'Вам нужно будет использовать ExecuteEvents.Execute, для которого целью события будет GameObject.

Кроме того, недостаточно изменять только входящие события указателя.Никакого события не происходит, когда мышь перемещается над чем-либо, но вам нужно будет проверить, должен ли находящийся поблизости объект все равно получить событие OnMouseEnter!

Вам понадобится код, который запускает каждый кадр и способен создавать и / или изменять PointerEventData, а затем выполнять соответствующее событие с ExecuteEvents

Я не знаю, есть ли способ перехватывать и отбрасывать события до того, как игровой объект их получит, но вы захотите помнить о своей системе и о том, как создать избыточные события.Например, ваша система выполнит OnMouseEnter OnMouseStay потенциально задолго до того, как встроенная, и вызываемой цели GameObject может потребоваться код для игнорирования встроенных выполнений этих событий.

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

Один из способов сделать это - установить Physics.queriesHitTriggers = true;, добавив дочерний GameObject с «более толстой» версией коллайдера (что именно это означает, может зависеть от исходного коллайдера), и установив его в качестве триггера, чтобычто это не мешает физике.Затем вы реализуете OnMouseEnter и т. Д. В сценарии этого дочернего объекта GameObject вместо исходного.

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