snozbot / fungus

An easy to use Unity 3D library for creating illustrated Interactive Fiction games and more.
MIT License
1.63k stars 291 forks source link

De/Activating MenuDialogs and autoSelectFirstButton interaction #974

Open TheEmbracedOne opened 3 years ago

TheEmbracedOne commented 3 years ago

I have an issue activating/deactivating MenuDialogs and autoSelectFirstButton:

In my game when you press the Pause button, the main MenuDialog gets deactivated (menuDialog.gameObject.SetActive(false)) then the pause menu which contains its own MenuDialog is activated.

Then when the Pause button is pressed again, I deactivate the pause menu and its MenuDialog, and reactivate the main MenuDialog.

However this presents an issue where activating/deactivating the pause menu sometimes loses button selection, despite the "auto first select" option being enabled on both MenuDialogs, leaving me with 0 buttons being selected.

Has anyone encountered this issue? How did you solve it?

Expected Outcome If a MenuDialog has been deactivated then reactivated, Fungus should attempt to select its first button if autoSelectFirstButton is enabled (and maybe if it's the only MenuDialog active).

Alternatives I have tried adding manual "button.Select();" and "EventSystem.current.SetSelectedGameObject(button.gameObject);" calls, but they dont always work for some reason (I've made sure they execute after the MenuDialog has been reactivated, but I suspect it might be clashing with the autoSelectFirstButton functionality).

TheEmbracedOne commented 3 years ago

Upon further investigation, this is not a Fungus issue - printing out EventSystem.current.currentSelectedGameObject prints out the correct button, it's just that it doesnt get the highlight.

Apparently, there's a Unity UI issue where if a button that is currently selected gets disabled, sometimes it remains selected even if its inactive, causing issues with the next selection: https://forum.unity.com/threads/cant-navigate-ui-with-arrow-keys-after-enabling-disabling-the-canvas.297990/#post-1965807

Maybe there's still something that could be done within Fungus to combat it.

Currently I can work around this by doing the following: 1) Right before the pause menu is activated and deactivated, I add EventSystem.current.SetSelectedGameObject(null); so when the other MenuDialog gets activated, it can select its first button without clash 2) I added an extra failsafe to one of my input scripts that, if it detects that currentSelectedGameObject is null, it re-checks after 1.50secs and if still null, finds the first active button in a list of buttons and selects it.

...but there might be a better solution.

edit: Since, I also added this safety measure to my MenuDialog.cs, this is to so that when MenuDialog object is deactivated, it checks whether the current selected gameobject was part of that MenuDialog and if so, it sets the eventsystem's current selected gameobject to null.

        private void OnDisable() {
            Button[] buttons = this.GetComponentsInChildren<Button>();
            for (int i = 0; i < buttons.Length; i++) {
                if (EventSystem.current.currentSelectedGameObject == buttons[i].gameObject) {
                    EventSystem.current.SetSelectedGameObject(null);
                }
            }
        }

Once again, not a pretty solution, and probably not a good one for longterm but it works for now.

breadnone commented 3 years ago

This is Unity's problem... You can try set the interactable of those buttons to false.. then set it back to true in the next line of your code