A few thoughts around this ... I'm honestly not keen to release my game to production with a
60 KB per second GC allocation. I believe it will cause issues on XBOX. I totally agree that this is a Unity bug... and unfortunately, the Unity team isn't likely to fix these IMGUI GC allocations, not now, not ever. IMGUI was replaced in 2015 by Unity UI and five years is ancient history to Unity developers Moreover, OnGUI() is broken by design because it allocates heap objects for eventing -- several hundred or thousand a second in some scenarios.
So what's the viable alternative to OnGUI? Since you asked... One approach is to use Input.GetMouseDown and Input.GetKeyboard. It is doable -- I'm sharing a working proof of concept here. I need to modify it further so that it handles multiple input events simultaneously, but for now, this expresses the concept and it works in my game.
* I edited my post to be more agreeable. I was tired and my initial thoughts didn't translate well.
1. Comment Out
//void OnGUI()
//{
// if (_uiView != null)
// {
// UnityEngine.GUI.depth = -(int)_myCamera.depth;
// ProcessEvent(UnityEngine.Event.current, _enableKeyboard, _enableMouse, _emulateTouch);
// }
//}
2.
Add:
private void Update()
{
if (_uiView != null)
ProcessEvent2(_enableKeyboard, _enableMouse, _emulateTouch);
}
3.
Add
private void ProcessEvent2(bool enableKeyboard, bool enableMouse, bool emulateTouch)
{
// Process keyboard modifiers
if (enableKeyboard)
{
EventModifiers currentModifiers = EventModifiers.None;
if (Input.GetKey(KeyCode.LeftShift))
currentModifiers |= EventModifiers.Shift;
if (Input.GetKey(KeyCode.LeftControl))
currentModifiers |= EventModifiers.Control;
EventModifiers delta = currentModifiers ^ _modifiers;
if (delta > 0)
{
_modifiers = currentModifiers;
ProcessModifierKey(currentModifiers, delta, EventModifiers.Shift, Key.LeftShift);
ProcessModifierKey(currentModifiers, delta, EventModifiers.Control, Key.LeftCtrl);
ProcessModifierKey(currentModifiers, delta, EventModifiers.Command, Key.LeftCtrl);
ProcessModifierKey(currentModifiers, delta, EventModifiers.Alt, Key.LeftAlt);
}
}
EventType eventType = EventType.Ignore;
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
eventType = EventType.MouseDown;
else if (Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1) || Input.GetMouseButtonUp(2)) // naieve approach given multiple inputs may fire simultaneously
eventType = EventType.MouseUp;
else if (Input.anyKeyDown)
eventType = EventType.KeyDown;
switch (eventType)
{
case UnityEngine.EventType.MouseDown:
{
if (enableMouse)
{
//UnityEngine.Vector2 mouse = ProjectPointer(Input.mousePosition.x, UnityEngine.Screen.height - Input.mousePosition.y);
UnityEngine.Vector2 mouse = new Vector2(Input.mousePosition.x, UnityEngine.Screen.height - Input.mousePosition.y);
//if (HitTest(mouse.x, mouse.y))
//{
// ev.Use();
//}
if (emulateTouch)
{
_uiView.TouchDown((int)mouse.x, (int)mouse.y, 0);
_touchEmulated = true;
}
else
{
// Ignore events generated by Unity to simulate a mouse down when a touch event occurs
bool mouseEmulated = Input.simulateMouseWithTouches && Input.touchCount > 0;
if (!mouseEmulated)
{
//if (ev.clickCount == 1)
//{
if (Input.GetMouseButtonDown(0))
_uiView.MouseButtonDown((int)mouse.x, (int)mouse.y, MouseButton.Left);
else if (Input.GetMouseButtonDown(1))
_uiView.MouseButtonDown((int)mouse.x, (int)mouse.y, MouseButton.Right);
else if (Input.GetMouseButtonDown(2))
_uiView.MouseButtonDown((int)mouse.x, (int)mouse.y, MouseButton.Middle);
//}
// TODO: store click count, if truly needed
//else
//{
//_uiView.MouseDoubleClick((int)mouse.x, (int)mouse.y, (Noesis.MouseButton)ev.button);
//}
}
}
}
break;
}
case UnityEngine.EventType.MouseUp:
{
if (enableMouse)
{
//UnityEngine.Vector2 mouse = ProjectPointer(Input.mousePosition.x, UnityEngine.Screen.height - Input.mousePosition.y);
UnityEngine.Vector2 mouse = new Vector2(Input.mousePosition.x, UnityEngine.Screen.height - Input.mousePosition.y);
//if (HitTest(mouse.x, mouse.y))
//{
// ev.Use();
//}
if (emulateTouch && _touchEmulated)
{
_uiView.TouchUp((int)mouse.x, (int)mouse.y, 0);
_touchEmulated = false;
}
else
{
// Ignore events generated by Unity to simulate a mouse up when a touch event occurs
bool mouseEmulated = Input.simulateMouseWithTouches && Input.touchCount > 0;
if (!mouseEmulated)
{
if (Input.GetMouseButtonUp(0))
_uiView.MouseButtonUp((int)mouse.x, (int)mouse.y, MouseButton.Left);
else if (Input.GetMouseButtonUp(1))
_uiView.MouseButtonUp((int)mouse.x, (int)mouse.y, MouseButton.Right);
else if (Input.GetMouseButtonUp(2))
_uiView.MouseButtonUp((int)mouse.x, (int)mouse.y, MouseButton.Middle);
}
}
}
break;
}
case UnityEngine.EventType.KeyDown:
{
if (enableKeyboard)
{
foreach (var kvp in NoesisKeyCodes._unityToNoesis)
{
if (Input.GetKeyDown(kvp.Key))
_uiView.KeyDown(kvp.Value);
}
}
break;
}
case UnityEngine.EventType.KeyUp:
{
//// Don't process key when IME composition is being used
//if (enableKeyboard)
//{
// if (ev.keyCode != KeyCode.None && NoesisUnity.IME.compositionString == "")
// {
// Noesis.Key noesisKeyCode = NoesisKeyCodes.Convert(ev.keyCode);
// if (noesisKeyCode != Noesis.Key.None)
// {
// _uiView.KeyUp(noesisKeyCode);
// }
// }
//}
break;
}
}
}