How do I create an Event Listener for Cursor.lockstate?

579 views Asked by At

I'd like to add an event listener for changes to Cursor.lockState in my unity WebGL game.

If the cursor is locked, I would like to unpause the game. If I detect the cursor has been unlocked I'd then like to pause.

Here is what I have so far

using UnityEngine;
using System.Collections;

public class Pause : MonoBehaviour {

public RotateCamera rotateCamera;
public GameObject pauseMenu;
private bool paused;

void Update()
{
    if (paused)
    {
        if (Input.GetMouseButtonDown(0))
        {
            UnpauseGame();
            return;
        }
    }
    if (Cursor.lockState == CursorLockMode.Locked)
    {
        Debug.Log("CursorLockMode = Locked");
        UnpauseGame();
        return;
    }
    if (Cursor.lockState == CursorLockMode.Confined)
    {
        Debug.Log("CursorLockMode = Confined");
        UnpauseGame();
        return;
    }

    if (Cursor.lockState == CursorLockMode.None && paused == false)
    {
        Debug.Log("CursorLockMode = None");
        PauseGame();
    }
}

public void PauseGame()
{
    Cursor.lockState = CursorLockMode.None;
    Cursor.visible = true;
    paused = true;
    pauseMenu.SetActive(true);
}

public void UnpauseGame()
{
    Cursor.lockState = CursorLockMode.Locked;
    Cursor.visible = false;
    paused = false;
    pauseMenu.SetActive(false);
}
}

The problem is

  • When trying to unpause the game with mouse button down the game instantly pauses itself. I believe the script detects that the cursor.lockstate is unlocked and instantly re-pauses the game.

To fix this, I think I need to create an event that listens to changes in the lock state and calls the method. Rather than the method being called every frame.

1

There are 1 answers

2
Programmer On

I think I need to create an event that listens to changes in the lock state and calls the method. Rather than the method being called every frame.

This is simple. Don't use the Cursor API directly. Wrap another class around it then use property getter and setter to implement a simple event system. Check out Unity's Events and Delegates tutorial here.

The wrapper AdvanceCursor.cs:

public class AdvanceCursor
{
    //Not needed but included just because Cursor has a pulbic constructor
    private Cursor cursor;

    public AdvanceCursor()
    {
        cursor = new Cursor();
    }

    public static CursorLockMode lockState
    {
        set
        {
            Cursor.lockState = value;

            //Notify Event
            if (OnLockStateChanged != null)
            {
                OnLockStateChanged(value);
            }
        }

        get { return Cursor.lockState; }
    }

    public static bool visible
    {
        set
        {
            Cursor.visible = value;

            //Notify Event
            if (OnVisibleChanged != null)
            {
                OnVisibleChanged(value);
            }
        }

        get { return Cursor.visible; }
    }

    public static void SetCursor(Texture2D texture, Vector2 hotspot, CursorMode cursorMode)
    {
        Cursor.SetCursor(texture, hotspot, cursorMode);

        //Notify Event
        if (OnTextureChanged != null)
        {
            OnTextureChanged(texture, hotspot, cursorMode);
        }
    }

    /////////////////////////////////////////////EVENTS//////////////////////////////////

    //Event For LockState
    public delegate void cursorLockStateAction(CursorLockMode lockMode);
    public static event cursorLockStateAction OnLockStateChanged;

    //Event For visible
    public delegate void cursorVisibleAction(bool visible);
    public static event cursorVisibleAction OnVisibleChanged;

    //Event For Texture Change
    public delegate void cursorTextureAction(Texture2D texture, Vector2 hotspot, CursorMode cursorMode);
    public static event cursorTextureAction OnTextureChanged;
}

USAGE:

Simply subscribe to the events.

public class CursorTest: MonoBehaviour
{
    void Start()
    {
        AdvanceCursor.lockState = CursorLockMode.Locked;
        AdvanceCursor.visible = true;
        //AdvanceCursor.SetCursor(...);
    }

    //Subscribe to Events
    void OnEnable()
    {
        AdvanceCursor.OnLockStateChanged += OnCursorLockStateChanged;
        AdvanceCursor.OnVisibleChanged += OnCursorVisibleChanged;
        AdvanceCursor.OnTextureChanged += OnCursorTextureChange;
    }

    //Un-Subscribe to Events
    void OnDisable()
    {
        AdvanceCursor.OnLockStateChanged -= OnCursorLockStateChanged;
        AdvanceCursor.OnVisibleChanged -= OnCursorVisibleChanged;
        AdvanceCursor.OnTextureChanged -= OnCursorTextureChange;
    }

    void OnCursorLockStateChanged(CursorLockMode lockMode)
    {
        Debug.Log("Cursor State changed to: " + lockMode.ToString());
    }

    void OnCursorVisibleChanged(bool visible)
    {
        Debug.Log("Cursor Visibility is now: " + visible);
    }

    void OnCursorTextureChange(Texture2D texture, Vector2 hotspot, CursorMode cursorMode)
    {
        Debug.Log("Cursor Texture Changed!");
    }
}