The DefaultEventSystem is a problem

In our game, it would be a lot cleaner to synthesize UI events and send them to our UITK UI than it is to use an event system.

The problem is that when I react to pressing wasd by doing this:

using var navigationEvent = NavigationMoveEvent.GetPooled(direction);
uiDocument.rootVisualElement.SendEvent(navigationEvent);

The cursor moves twice - once from my code, and once from DefaultEventSystem. By looking at the debugger, it seems like if there’s no event system registered with the internal UIElementsRuntimeUtility, a default one will be used.

This seems strange! I can understand the idea of having input “just work” if you have forgotten to put an EventSystem in the scene, but that removes our option of not having an input system at all.

The workaround I can find seems very silly - creating an EventSystem with no InputModule. But I’d really like to not have a bunch of code running and objects created in order to trick the system into not doing anything. Help?

1 Like

I randomly stumbled over a post today which mentioned this:

Internally, UI Toolkit installs an event listener in the form of the PanelEventHandler component which intercepts events that InputSystemUIInputModule sends and translates them into UI Toolkit-specific events that are then routed into the visual tree. If you employ EventSystem.SetUITookitEventSystemOverride, this default mechanism is bypassed.

https://docs.unity3d.com/Packages/com.unity.ugui@2.0/api/UnityEngine.EventSystems.EventSystem.html#UnityEngine_EventSystems_EventSystem_SetUITookitEventSystemOverride_UnityEngine_EventSystems_EventSystem_System_Boolean_System_Boolean_
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.1/manual/UISupport.html#ui-toolkit-support

That still sounds similar to your eventsystem with no input module suggestion, but maybe a tiny tiny bit cleaner?

2 Likes

EventSystem.SetUIToolkitEventSystemOverride requires me to send in an EventSystem instance - if I send in null, then that’s treated as “use the fallback”, not “I specifically want you to not do stuff”. All the code treats sending null to the method as not calling the method at all. Womp womp.

I guess if I wanted to really deactivate everything, I could subclass EventSystem, override every single virtual method to do nothing, set that as the UI Toolkit override, and hope that it doesn’t break anything.

1 Like

Maybe this works. Bit of a workaround.

var handlers = FindObjectsByType<PanelEventHandler>(FindObjectsSortMode.None);
        foreach (PanelEventHandler handler in handlers)
        {
            if (handler.panel == doc.rootVisualElement.panel) // My panel?
            {
                handler.enabled = false;
                break;
            }
        }
1 Like

You can create an EventSystem, pass it to SetUIToolkitEventSystemOverride and also specify
createPanelGameObjectsOnStart = false. It should make it so that the DefaultEventSystem doesn’t overtake the events but the EventSystem also doesn’t forward them, leaving you with a quiet environment for UI Toolkit.

Try calling SetUIToolkitEventSystemOverride before your EventSystem.Start method is called though, to avoid the PanelEventHandlers from being already created (or you can delete them later manually).

var handlers = FindObjectsByType<PanelEventHandler>(FindObjectsSortMode.None);
foreach (PanelEventHandler handler in handlers)
{
  if (handler.panel == doc.rootVisualElement.panel) // My panel?
  {
      handler.enabled = false;
      break;
  }
}

This actually works!

You can create an EventSystem, pass it to SetUIToolkitEventSystemOverride and also specify
createPanelGameObjectsOnStart = false. It should make it so that the DefaultEventSystem doesn’t overtake the events but the EventSystem also doesn’t forward them, leaving you with a quiet environment for UI Toolkit.
Try calling SetUIToolkitEventSystemOverride before your EventSystem.Start method is called though, to avoid the PanelEventHandlers from being already created (or you can delete them later manually).

Doing this makes my game start spamming the “There are 2 sevent systems in the scene” warning. Did I miss some part of this?

There are 2 event systems in the scene

Strange. Are there? Did you create one, then delete it and create another one? Do you get the same problem if you do it in an empty project, empty scene, and no fancy build profile? I’m trying to understand if there’s something else happening in the background somehow.

This actually works!

Nice! I’m glad that you at least have a workaround. I’m a bit disappointed that my “recommended workaround” doesn’t work though. :-/