decentraland / decentraland/unity-explorer

PrimaryPointerInfo screenCoordinates/screenDelta use bottom-left Y-up instead of top-left Y-down

Open Beginner friendly
#10,073 1 comment 0 reactions 0 assignees View on GitHub
1-high bug sdk
Dominant language
C#
Stars
23
Forks
17
Avg merge
2d 19h
Merged PRs (30d)
107

Description

## Summary

`PrimaryPointerInfo.screenCoordinates` and `screenDelta` are reported with a **bottom-left origin / Y up** (Unity's native screen space). Bevy and Godot report **top-left origin / Y down**, which is also the coordinate space of `UiTransform` / `UiCanvasInformation`. Scenes that compare the pointer against UI rects, or feed `screenDelta` into a `VirtualCamera` look, get a vertically mirrored cursor and inverted pitch on Unity only.

## Where

`Explorer/Assets/DCL/SDKComponents/PrimaryPointerInfo/Systems/PrimaryPointerInfoSystem.cs` — `UpdatePointerInfo()` writes `inputPoint.ReadValue()` (Unity screen space, Y up) and the accumulated `Camera.Delta` straight into `ScreenCoordinates` / `ScreenDelta`.

For comparison:
- Bevy: `crates/scene_runner/src/update_scene/pointer_lock.rs` uses `Window::cursor_position()` (top-left, Y down) and the mouse-motion delta (Y down).
- Godot: `lib/src/scene_runner/scene_manager.rs` uses the viewport mouse position (top-left, Y down) and its frame difference.

The [SDK docs](https://docs.decentraland.org/creator/development-guide/sdk7/system-based-events/) specify a top-left origin with Y increasing downward, matching `UiTransform`. The proto comment only says "screen space (pixels)", so documenting the convention there too would help. Suggested fix: `y = Screen.height - y` for the position and negate `delta.y`.

This was reported for `screenCoordinates` in #8757 (closed by the stale bot, not fixed); this issue adds the `screenDelta` half and a repro scene.

## How to validate

Minimal SDK7 scene: a 40x40 square follows the pointer using `screenCoordinates` in UI canvas space, and the log prints the delta sign while the pointer is locked.

```ts
import { engine, PrimaryPointerInfo, UiCanvasInformation, PointerLock } from '@dcl/sdk/ecs'
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export function main() {
ReactEcsRenderer.setUiRenderer(() => {
const cursor = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenCoordinates
const canvas = UiCanvasInformation.getOrNull(engine.RootEntity)
if (!cursor || !canvas) return null
return (

)
})

engine.addSystem(() => {
if (!PointerLock.getOrNull(engine.CameraEntity)?.isPointerLocked) return
const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
if (delta && Math.abs(delta.y) > 2) console.log(delta.y > 0 ? 'delta.y > 0' : 'delta.y < 0')
})
}
```

Expected (Bevy, Godot): the red square sits under the cursor; moving the mouse **down** logs `delta.y > 0`.
Actual (Unity): the square is mirrored vertically (top of screen when the cursor is at the bottom); moving the mouse **down** logs `delta.y < 0`.

Contributor guide

Open the contributing guide

Research direction

Start in Explorer/Assets/DCL/SDKComponents/PrimaryPointerInfo/Systems/PrimaryPointerInfoSystem.cs at UpdatePointerInfo(), where inputPoint and Camera.Delta are assigned to ScreenCoordinates and ScreenDelta. Validate with the minimal SDK7 repro scene: the red square should stay under the cursor, and moving the mouse down should log a positive delta.y as in Bevy and Godot.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, unity
Domain
game-dev
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.