I have a Screen Space - Overlay canvas with some right-aligned buttons:
The container looks like this:
Each button looks like this:
Conditions:
- Built player only (it seems)
- Window needs to be maximised, or fairly large
- Is dependant on the X Pos of the ToolIcons container. Depending on window resolution, it can be something like XPos of -116 - all works fine, -117 … it’s broken
The problem:
- While rendering is fine, mouse-over interactions (highlights, clicks) are misaligned. usually, the Y coord is offset such that the button below highlights the button above
- This includes the fact that the cursor over the top icon does nothing, and moving the mouse over the space beneath the bottom icon highlights the bottom icon
- Depending on X Position of the right-align, or window size, sometimes it’ll instead be that the Y offset is gone, but only the left half of the icons trigger the interactions
It does seem like a bug - surely the same layout values and logic should be used for rendering and hit-testing?
I have tried:
- Trying to recreate in editor play mode
- Checking console for any warning/error output - none
- Disabling the custom DP Canvas Scaler / using a regular canvas scaler
- A few hours’ googling/forum searching
- Playing with anchor/pivot settings on the buttons
- Checking all the transforms have a scale of 1, no rotation, etc
- Weeping gently
My questions:
- Is anyone aware of this scenario / bug?
- Any suggestions for diagnosing further?
Update - it’s not just those buttons. The right-hand side of the screen, even at 1080p resolution - a Y offset is introduced as I move the cursor to the right.
E.g. if I have a list of dropdowns in a modal window near the right… when I move the mouse across the width of one, the current (correct) dropdown starts off highlighted, but as I go to the right, the one above does instead.
How/why would there be Y offset “warping” at the right-hand side of the screen??
UPDATE - I added some debug output to show Mouse.current.position, the GraphicRaycaster.Raycast first result’s screenPosition, and the offset between the two:
When the mouse cursor X is 1857 or greater, the raycast screenPosition’s Y value gets an offset of 35.
Ok, I’ve been debugging the raycast code. it’s MultipleDisplayUtilies.RelativeMouseAtScaled that applies the offset. It has conditional logic for build mode only.
Below is the Unity code where the bug is.
See the comment, “If we are not inside of the main display”. This clause is triggered and adds an offset. However, the assumption is faulty: we ARE inside the main display.
That means “widthPlusRightPadding” is incorrect.
My values:
Screen.fullScreen = false
Display.main.renderingWidth = 1920
Display.main.renderingHeight = 1009
Display.main.systemWidth = 1920
Display.main.systemHeight = 1080
widthPlusPadding = 1793
widthPlusRightPadding = 1856
I don’t know what “padding” its referring to here. But my renderingWidth is 1920, my systemWidth is 1920, I don’t know why any offset is applied at “widthPlusRightPadding”.
// If the main display is now the same resolution as the system then we need to scale the mouse position. (case 1141732)
if (Display.main.renderingWidth != Display.main.systemWidth || Display.main.renderingHeight != Display.main.systemHeight)
{
// Calculate any padding that may be added when the rendering apsect ratio does not match the system aspect ratio.
int widthPlusPadding = Screen.fullScreen ? Display.main.renderingWidth : (int)(Display.main.renderingHeight * (Display.main.systemWidth / (float)Display.main.systemHeight));
// Calculate the padding on each side of the screen.
int padding = Screen.fullScreen ? 0 : (int)((widthPlusPadding - Display.main.renderingWidth) * 0.5f);
int widthPlusRightPadding = widthPlusPadding - padding;
// If we are not inside of the main display then we must adjust the mouse position so it is scaled by
// the main display and adjusted for any padding that may have been added due to different aspect ratios.
if ((position.y < 0 || position.y > Display.main.renderingHeight ||
position.x < 0 || position.x > widthPlusRightPadding))
{
if (!Screen.fullScreen)
{
// When in windowed mode, the window will be centered with the 0,0 coordinate at the top left, we need to adjust so it is relative to the screen instead.
position.x -= (Display.main.renderingWidth - Display.main.systemWidth) * 0.5f;
position.y -= (Display.main.renderingHeight - Display.main.systemHeight) * 0.5f;
}
Ok, finding that method led me to:
Mouse input does not work on right side of screen in windowed build .
I also raised incident IN-15001.
And the temporary fix;
A fix is on the way. You can work around the issue now by moving the UGUI package from the PackageCache folder into the projects Packages folder. Then replace the file MyProject\Packages\com.unity.ugui\Runtime\UI\Core\MultipleDisplayUtilities.cs with this one Workaround to UGUI input issues https://issuetracker.unity3d.com/issues/broken-mouse-pointer-input-coordinates-in-graphicraycaster-for-certain-window-sizes-in-build-when-run-in-windowed-mode · GitHub