I think there should be a neater way to do this, but here's what I have working so far (based on a more involved example with curved UI here)....
We'll remove the usual StandaloneInputModule, which uses the mouse as the cursor position, and replace it with our own version that always treats the mouse as being in the center of the screen - at the reticle.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class FPSInputModule : StandaloneInputModule {
protected override MouseState GetMousePointerEventData(int id = 0)
{
var reticlePosition = new Vector2(Screen.width/2, Screen.height/2);
MouseState mouseState = new MouseState();
PointerEventData leftData;
var created = GetPointerData(kMouseLeftId, out leftData, true);
leftData.Reset();
leftData.delta = reticlePosition - leftData.position;
leftData.position = reticlePosition;
leftData.scrollDelta = Input.mouseScrollDelta;
leftData.button = PointerEventData.InputButton.Left;
eventSystem.RaycastAll(leftData, m_RaycastResultCache);
var raycast = FindFirstRaycast(m_RaycastResultCache);
leftData.pointerCurrentRaycast = raycast;
m_RaycastResultCache.Clear();
// copy the apropriate data into right and middle slots
PointerEventData rightData;
GetPointerData(kMouseRightId, out rightData, true);
CopyFromTo(leftData, rightData);
rightData.button = PointerEventData.InputButton.Right;
PointerEventData middleData;
GetPointerData(kMouseMiddleId, out middleData, true);
CopyFromTo(leftData, middleData);
middleData.button = PointerEventData.InputButton.Middle;
mouseState.SetButtonState(PointerEventData.InputButton.Left, StateForMouseButton(0), leftData);
mouseState.SetButtonState(PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
mouseState.SetButtonState(PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);
return mouseState;
}
}
This correctly handles clicking, but it's currently not working for hover. I think it's because as the camera rotates to bring the cursor over a new point in space, the cursor's positional delta is still zero - it's still in the center of the screen - so the event system doesn't realize it needs to re-evaluate the hover states of UI elements.