切换统一事件系统目标

时间:2019-06-05 18:15:40

标签: c# unity3d

我想用我通过代码在其他地方手动指定的系统来代替统一事件系统的目标。

这是为了允许常规的统一事件适当地触发附近的对象,即使指针可能不直接位于目标上。 (目标辅助/指针捕捉/稳定)

我的问题是,即使我用所需的目标更新事件系统的选定游戏对象,统一事件系统也不会触发,因为它仍然认为指针不在目标之上。 (尽管编辑器事件系统调试对话框和“突出显示”效果(用于UI元素)也会相应触发,并显示所选目标已更改。)

//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组件上将指针捕捉到目标,从而启用基于目标捕捉指针的选择。一旦“非GUI”目标被“捕捉”,我就使用ExecuteEvents.ExecuteHierarchy for IPointerEnter / Exit / Down / Up / Click来根据需要手动触发事件。

但是对于GUI组件目标,如果我利用相同的自定义事件代码,则会失去与更复杂,动态GUI组件进行交互的能力,而没有多种变通方法,并且向每个GUI元素添加了对撞机。我希望避免重新设计unity的输入模块以支持指针捕捉,因为一旦指针进入边界,默认输入模块就可以很好地在GUI组件上使用。

-编辑2-

我应该补充一点,我使用Unity的HoloLensInputModule和HoloLensInput处理UI交互,同时使用自己的raycast处理非UI组件。

似乎我需要用我的捕捉代码扩展HoloLensInput.cs的GetGazeScreenPosition()以便不再需要关注更新事件系统

-大部分已解决-

我已经通过扩展StandaloneInputModule和BaseInput并在其继承结构中覆盖多个方法来解决该问题。 (这很丑陋,但是可以正常运行,因为我可以掉掉多余的RaycastAll通话)

问题的症结在于不仅要覆盖深埋在继承的类中的RaycastAll调用,而且要覆盖任何请求或操纵eventData的时间。大部分更改与GetMousePointerEventData()ProcessMouseEvent()有关,并且几乎所有方法调用都以递归方式链接在其中,包括子级。

话说回来,滚动条存在问题,滚动条在最小滚动和最大滚动之间跳转。问题似乎来自ProcessDrag()'s ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);

之后滑块内部使用的指标eventData.position值

1 个答案:

答案 0 :(得分:0)

第一个问题是SetSelectedGameObject不会将事件发送或转发到游戏对象。用于更改事件系统作为选定游戏对象跟踪的内容,并可以发送OnSelectOnDeselect事件。

如果您想实际执行具有特定目标的事件,则需要使用ExecuteEvents.Execute,该事件将GameObject用作事件的目标。

此外,仅修改传入的指针事件还不够。鼠标悬停在上方时,不会发生任何事件,但是无论如何,您需要检查附近的对象是否需要接收OnMouseEnter事件!

您将需要运行每一帧的代码,并能够创建和/或修改PointerEventData,然后使用ExecuteEvents执行相应的事件

我不知道在游戏对象收到事件之前是否有办法拦截和丢弃事件,但是您需要注意自己的系统和执行冗余事件的构建。例如,您的系统可能会在内置系统执行OnMouseEnter OnMouseStay之前很久执行,并且调用目标GameObject可能需要代码来忽略这些事件的内置执行

根据您的情况,使用内置事件并使用较大的对撞机(仅用于接收鼠标事件)可能更容易。

一种方法是设置Physics.queriesHitTriggers = true;,添加带有对撞机“更厚”版本的子GameObject(确切的含义可能取决于原始对撞机),并将其设置为触发器,以便它不会干扰物理。然后,在该子GameObject的脚本中而不是原始的脚本中实现OnMouseEnter等。