凝视总是在PointExit之后执行

时间:2019-02-11 04:46:40

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

我对VR的凝视有一个问题。我想做的是凝视我要选择的按钮,然后隐藏第一个游戏对象父对象,然后显示第二个游戏对象父对象。现在将显示第二个游戏对象父对象,当我尝试凝视后退按钮时,它将显示第一个游戏对象父对象并隐藏第二个游戏对象父对象。问题出现在这里,当我什么都不做并且不注视按钮时,它会自动显示我的第二个游戏对象父对象,然后返回第一个父游戏对象并隐藏并显示并始终隐藏并显示。

public float gazeTime = 2f;
private float timer;
private bool gazedAt;

public Setting setting;

private void Start()
{

}

public void Update()
{
    if (gazedAt)
    {
        timer += Time.deltaTime;

        if (timer >= gazeTime)
        {
            // execute pointerdown handler
            ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerDownHandler);
            timer = 0f;
        }
        else
        {
            return;
        }
    }
    else
    {
        return;
    }

}

public void PointerEnter()
{
    gazedAt = true;
    Debug.Log("PointerEnter");
}

public void PointerExit()
{
    gazedAt = false;
    Debug.Log("PointerExit");
}

//Method for going to setting
public void Setting()
{
    setting.ActivateSetting();
}
//Method for going back to main menu
public void GoBack()
{
    setting.GoBackToMainMenu();
}

这是我的Setting代码的设置方式

public GameObject setting;
public GameObject back; 

public void ActivateSetting()
{
    setting.SetActive(false);
    back.SetActive(true);
}

public void GoBackToMainMenu()
{
    back.SetActive(false);
    setting.SetActive(true);
}  

我想要的是,如果我凝视它,它只会显示游戏对象的父对象。

1 个答案:

答案 0 :(得分:1)

点击一次后,您重置了timer,但没有重置gazedAt

=> Update方法仍在运行计时器并再次调用该点击。

您的PointerExit似乎根本没有被调用,因此该按钮永远不会重置。


我强烈建议使用IPointerEnterHandlerEventTrigger这样的接口,而不是IPointerExitHandler

public class YourClass : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    //...

    public void OnPointerEnter()
    {

    }

    public void OnPointerExit()
    {

    }

我实际上根本不会使用Update,而是更喜欢Coroutine。另外,请勿使用ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerDownHandler);的复杂调用,而应使用Getcomponent<Button>().onClick.Invoke();或直接调用该方法

private Button _button;

private void Awake()
{
    // Get the reference only once to avoid 
    // having to get it over and over again
    _button = GetComponent<Button>();
}

private IEnumerator Gaze()
{
    // wait for given time
    yield return new WaitForSeconds(gazeTime);

    // call the buttons onClick event
    _button.onClick.Invoke();

    // or as said alternatively directly use the methods e.g.
    setting.ActivateSetting();
}

public void OnPointerEnter()
{
    Debug.Log("PointerEnter");

    // start the coroutine
    StartCoroutine(Gaze());
}

public void OnPointerExit()
{
    Debug.Log("PointerExit");

    // stop/interrupt the coroutine
    StopCoroutine(Gaze());
}

如您所见,timergazedAt值根本不需要,因此您不能忘记将它们重置在某个地方。它还避免了重复调用该方法。


如果您根本不想使用Button,也可以添加自己的UnityEvent,例如

// add callbacks e.g. in the Inspector or via script
public UnityEvent onGazedClick;

// ...

onGazedClick.Invoke();