I’m struggling to get current button focus and highlight to stay in-sync.
I have a couple of layouts, one is deactivated. I use a button to activate it and deactivate the current one.
The problem is when I go back and re-activate the original layout the button I clicked on is in a highlighted state except it is not actually the selected item, according to the EventSystem.
I’ve track this down to a problem when switching between mouse and keyboard. It seems that a button remembers it’s selected state even though the EventSystem has a different selected object.
This seems to be a combination of problems with the StandaloneInputModule and Selectable classes. I’ve run a script attached to my UI button and inspected some of the hidden parameters. There is a property called m_CurrentInputMode. This is either set to ‘Buttons’ or ‘Mouse’ depending on if I’m using the keyboard or mouse. However it’s private and there doesn’t seem to be anyway for me to find out what sort of input is being used. A ‘Selectable’ object has a private property called ‘hasSelection’. If this is true and I activate the layer it will always cause the object to go into a highlighted state.
I sort of have a work around for this situation by looping through all the Selectable objects on a layer and call OnDeselect() when I enable the layer. This seems to set the ‘hasSelection’ bool to false. I can select the correct button using the EventSystem. However I can only do this part if the user is using a keyboard, which I can’t find out as the m_CurrentInputMode is private.
The best idea I have so far is to implement by own version of StandaloneInputModule but that seems a bit excessive.
Has the C# source code for the new UI system been released yet? I can always get this and try and track down what the problem may be.
I’ve attached a example project that demos the issues.
There is a signal script, called ActiveScreen.cs, attached to each GameObject that acts as a screen.
In the OnEnable() method I’ve put in 3 separate #defines to enable default behaviour and a few workarounds I’ve tried.
At the top of the script there are some repro steps so you can see the various issues and you can turn on one #define at a time to see the different issues.
I can well understand why there maybe some edge cases in the UI system. I’ve built UI solutions myself over the last 15 years in this industry and there are always issues especially with input, focus and selection management.
I suppose this is a bit unfair of me to stress test the UI as it’s still only beta but from bitter experience I know where most of the pitfalls will be. I’ve had many games rejected for some TCR violation due to input issues. However any help is much appreciated. I constantly hear from fellow programmers that ‘UI is easy’. Oh no it’s not.
The workaround test still won’t actually be acceptable for a final project. It does make it possible to control a UI via either mouse or keyboard, but you can switch between the two. Switching input method or having simultaneous controller and pointer input should be possible. Many PC games will allow a user to plug in a 360 controller and if you start pressing controller buttons the input device will swap without problems.
Also on consoles it is possible to use both a controller and pointer input (e.g. Kinect). What is even more complex is allowing multiple players to control the UI. This doesn’t happen very often but I have known it to occur in games where the players can simultaneously select from a grid of possible avatars. However that usually requires some custom coding. There does need we may need a way to trigger a highlight from code, or maybe we just trigger an animator from code.
I do have to add that the UI system so far is very good. It’s nice to see a distinction between a visual state like highlighted and which item is focused for input. So many UI systems I’ve worked on didn’t do this and that caused its own issues. Its good to see some thought has been put into the design.
Thanks for the nice example project. I can really see what you want to do now. I have made some changes to what we expose on the Event system to make this possible, but basically the idea is that just by activating a game object does not select the element, you need to mark it selected in the Event system. In your case you want to only do this if you are using Keyboard input.
So when the next version is available, something like this is what you want:
public void SetSelectedIfUsingKeyboard (GameObject go)
{
if (EventSystemManager.currentSystem == null)
return;
var standAlone = EventSystemManager.currentSystem.currentInputModule as StandaloneInputModule;
if (standAlone == null)
return;
if (standAlone.inputMode != StandaloneInputModule.InputMode.Mouse)
EventSystemManager.currentSystem.SetSelectedGameObject(go);
}
So disable one menu, enable second menu, then call the SetSelectedIfUsingKeyboard function.
in 5.3 (maybe before that) yes the obsolete message should have told you that ““Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.””
Yeah, but how are we supposed to figure out which mode the user is using now? We don’t want to visually highlight a Selectable when we show a new screen. The screen transition example on the unity manual is actually using that method to determine this, which is now no longer possible.
We should update that how to then. As for the proper new solution i dont really have one. The deprecation happened at different times and this case was missed. Could someone file a bug just describing the issue
I’ll set up a bug later today and post the number here. Question though: Are you considering a way to enable that functionality? A lot of flexible UIs would need to change their behavior based on the input method…