Search code examples
c#unity-game-enginevirtual-realitygaze-buttons

gaze always execute even after PointExit


I have a problem about my gaze on VR . What I am trying to do is that gaze upon the button I want to select then hide the first gameobject parent then show the second gameobject parent . Now the second gameobject parent will be shown and when I try to gaze upon the back button it will show the first gameobject parent and hide the second gameobject parent . The problem occurs here, when I am trying to nothing and don't gaze on the buttons it automatically show my second gameobject parent and go back to first parent gameobject and hide and show and hide and show always.

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();
}

Here's how my Setting code is setup

public GameObject setting;
public GameObject back; 

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

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

What I want is that it will only show the gameobject parent if I gaze upon it.


Solution

  • After calling the click once you reset the timer but you didn't reset gazedAt

    => the Update method did still run the timer and call the click again.

    It seems that your PointerExit is not called at all and therefore the button never reset.


    Instead of the EventTrigger I would strongly recommend to use the interfaces IPointerEnterHandler and IPointerExitHandler like

    public class YourClass : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
    {
        //...
    
        public void OnPointerEnter()
        {
    
        }
    
        public void OnPointerExit()
        {
    
        }
    

    I would actually not use Update at all but prefer a Coroutine. Also don't use the complex call of ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerDownHandler); instead use either Getcomponent<Button>().onClick.Invoke(); or call the method directly

    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());
    }
    

    As you can see there is no need at all for the timer and gazedAt values so you can't forget to reset them somewhere. It also avoids that the method is called repeatedly.


    If you don't want to use a Button at all you could also add your own UnityEvent like

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