0
\$\begingroup\$

I have this UI with buttons that should be clickable whenever the UIDocument is enabled, but for some reason whenever I disable and then re-enable the UIDocument (in the second code block), the buttons are no longer clickable even though the UI shows up. This is the UI code:

public class UI : MonoBehaviour
{
    public BattleSystem battleSystem;
    void Start(){
        VisualElement root = GetComponent<UIDocument>().rootVisualElement;
     
        Button grenadeButton = root.Q<Button>("Grenade");
        Button pistolButton = root.Q<Button>("Pistol");

        grenadeButton.clicked += () => StartCoroutine(battleSystem.useWeapon(Weapon.GRENADE));
        pistolButton.clicked += () => StartCoroutine(battleSystem.useWeapon(Weapon.PISTOL));
    }
}

And this is the code in the BattleSystem class:

public IEnumerator useWeapon(Weapon weapon){
        Debug.Log("Button was pressed");
        StopCoroutine(turn); // stops the takeTurn Coroutine
        switch (weapon){
            case Weapon.GRENADE:
                yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
                Debug.Log("Powering Grenade");
                yield return new WaitUntil(() => !Input.GetKey(KeyCode.Space));
                Debug.Log("Grenade thrown");
                break;
            case Weapon.PISTOL:
                yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
                Debug.Log("Pistol fired");
                break;
        }
        yield return new WaitUntil(() => Input.GetKeyDown(weaponsKey));
        yield return new WaitUntil(() => !Input.GetKey(weaponsKey));
        StartCoroutine(takeTurn(currentPlayer));
    }
IEnumerator takeTurn(GameObject player){
        currentPlayer = player;
        LoadCameraToPlayer(currentPlayer);
        currentPlayer.GetComponent<PlayerMovement>().enabled = true;
        BattleState currentState = state;
        while (state == currentState){
            yield return new WaitUntil(keyPress);
            switch (pressedKey){
                case var v when v == passKey:
                    StartCoroutine(TurnEnd()); // changes state to break out of loop
                    break;
                case var v when v == weaponsKey:
                    yield return new WaitUntil(() => !Input.GetKey(weaponsKey));
                    updateWeaponUIState(!weaponWheel.GetComponent<UIDocument>().enabled); // turn on/off weapon UI upon pressing and releasing the weapons key
                    currentPlayer.GetComponent<PlayerMovement>().enabled = !weaponWheel.GetComponent<UIDocument>().enabled; // player movement
                    break;
            }
        }
    }
    void updateWeaponUIState(bool active){
        weaponWheel.GetComponent<UIDocument>().enabled = active;
        UnityEngine.Cursor.visible = active;
        if (active){
            UnityEngine.Cursor.lockState = CursorLockMode.Confined;
        } else{
            UnityEngine.Cursor.lockState = CursorLockMode.Locked;
        }
        tpc.enabled = !active; //ThirdPersonCamera
        cfl.enabled = !active; //CinemaFreeLook
    }

The buttons in the UI class work when I first enable the UIDocument (it starts disabled) but not after disabling and re-enabling it. Things I've tried:

  • Removing and adding the listeners back onto the buttons with OnEnable/OnDisable - I don't think you can remove listeners in UIElements so that doesn't work, but I think Start() should be best
  • Disabling the UIDocument GameObject instead of the Component - made no difference
  • Stopping (and not stopping) the takeTurn Coroutine before starting the useWeapon Coroutine. I thought maybe running two related coroutines simultaneously was the problem, it wasn't

Does anyone have any clue what the issue could be?

\$\endgroup\$
2
  • \$\begingroup\$ So I can click the Pistol Button, then the Grenade Button, then press down the space bar, which then does both "Pistol fired" and "Powering Grenade". Letting off the space bar does "Grenade thrown" and now when WeaponsKey is pressed down and released both go into takeTurn. While a fascinating use of Coroutines, I think I don't like this code because you can be at multiple WaitUntil() here and each one is completely independent of any other. In total, it is hard to tell what the complete state is as you could be focused on one WaitUntil() and ALSO be in any other, making debugging challenging. \$\endgroup\$
    – Dustin_00
    Commented Oct 14, 2023 at 13:57
  • \$\begingroup\$ No worries, I figured out the UI issue. And I fixed the overlapping inputs problem, just used some variables to keep track of whether the coroutine started and whether the user had fired the weapon (point of no return) \$\endgroup\$
    – skundu
    Commented Oct 15, 2023 at 9:10

1 Answer 1

0
\$\begingroup\$

This person figured it out, had to change the display mode instead of enable/disable, https://forum.unity.com/threads/why-cant-i-press-this-button-after-re-enabling-the-ui.1505888/

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for the answer, but link-only answers won't suffice, in case the original source goes away. Can you please summarize the post so that it can stand on its own? \$\endgroup\$
    – Evorlor
    Commented Oct 17, 2023 at 17:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .