【问题标题】:OnPointerEnter is not being calledOnPointerEnter 未被调用
【发布时间】:2020-05-23 15:25:21
【问题描述】:

我正在尝试在按钮被注视时为其设置动画。我有以下代码,我在其中从球体中投射光线以找到它击中的按钮。

var eventDataCurrentPosition = new PointerEventData(EventSystem.current);
        eventDataCurrentPosition.position = screenPosition;

var results = new List<RaycastResult>();

EventSystem.current.RaycastAll(eventDataCurrentPosition, results);

foreach (var result in results)
{
     Debug.Log(result.gameObject.name);
}  

为了为按钮设置动画,我将以下代码添加到按钮中。不幸的是,OnPointerEnter 或 ``OnPointerExit 永远不会被调用。

[RequireComponent(typeof(Button))]
public class InteractiveItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    public Image  progressImage;
    public bool   isEntered = false;
    RectTransform rt;
    Button        _button;
    float         timeElapsed;
    Image         cursor;
    float         GazeActivationTime = 5;

// Use this for initialization
void Awake()
{
    _button = GetComponent<Button>();
    rt      = GetComponent<RectTransform>();
}


void Update()
{
    if (isEntered)
    {
        timeElapsed              += Time.deltaTime;
        progressImage.fillAmount =  Mathf.Clamp(timeElapsed / GazeActivationTime, 0, 1);
        if (timeElapsed >= GazeActivationTime)
        {
            timeElapsed = 0;
            _button.onClick.Invoke();
            progressImage.fillAmount = 0;
            isEntered                = false;
        }
    }
    else
    {
        timeElapsed = 0;
    }
}

#region IPointerEnterHandler implementation

public void OnPointerEnter(PointerEventData eventData)
{
    CodelabUtils._ShowAndroidToastMessage("entered");
    isEntered = true;
}

#endregion

#region IPointerExitHandler implementation

public void OnPointerExit(PointerEventData eventData)
{
    CodelabUtils._ShowAndroidToastMessage("exit");

    isEntered                = false;
    progressImage.fillAmount = 0;
}

#endregion
}

我错过了什么吗?或者还有其他方法可以实现吗?

【问题讨论】:

    标签: c# unity3d user-interface virtual-reality gaze-buttons


    【解决方案1】:

    我猜你的 Raycast 应该会在所有结果上触发 OnPointerEnter

    您需要使用ExecuteEvents.Execute,例如

    ExecuteEvents.Execute(result.gameObject, eventDataCurrentPosition, ExecuteEvents.pointerEnterHandler);
    

    并且在某些时候还必须调用pointerExitHandler

    因此我会像这样存储一个 HashSet

    using System.Linq;
    
    private HashSet<GameObject> previousEnters = new HashSet<GameObject>();
    
    ...
    
    foreach (var result in results.Select(r => r.gameObject))
    {
        Debug.Log(result.name);
        ExecuteEvents.Execute(result, eventDataCurrentPosition, ExecuteEvents.pointerEnterHandler);
        // Store the item so you can later invoke exit on them
        if(!previousEnters.Contains(result)) previousEnters.Add(result);
    }  
    
    // This uses Linq in order to get only those entries from previousEnters that are not in the results
    var exits = previousEnters.Except(results);
    foreach(var item in exits)
    {
        if(item) ExecuteEvents.Execute(item, eventDataCurrentPosition, ExecuteEvents.pointerExitHandler);
    }
    

    您实际上可能想要实现自己的自定义PointerInputModule


    替代/示例

    作为初学者,您还可以使用我不久前对Using Raycast instead of Gaze Pointer 的回答,当时我基于 Steam 的 VR Laserpointer 创建了一个脚本,该脚本允许与 3D 对象和 UI 元素进行交互。


    注意:在智能手机上输入,但我希望思路清晰

    【讨论】:

    • 谢谢!我在 Unity 文档中的任何地方都找不到这个 - 尽管这个 API 已经“生产就绪”一年多了。您是否通过反复试验弄清楚了这一点?或者是否有来自 Unity 的文档可供我们参考,但我没有找到?
    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2016-05-21
    • 2012-02-15
    • 2011-11-17
    • 2019-10-22
    相关资源
    最近更新 更多