Skip to content

Screen Space - Camera canvases mis-scale and follow the viewer: Camera.fieldOfView is XR-written while a session runs #274

Description

@dfattal

Reported by a partner integrator during the LeiaViewer port (internal ticket UNITY-133), while trying to build a flat 2D home screen.

Symptom

A Screen Space - Camera canvas inside a running DisplayXR app:

  • renders 1.4–3.3x too large, and
  • rescales and drifts as the viewer's head moves.

Removing the DisplayXR rig from the camera does not help: the session still drives that camera with a head-tracked projection ("look-around mono"), so the whole UI floats with the viewer's face. No rig != no tracking.

Mechanism

While a session is running, the provider hands Unity a full per-eye projection, and Unity's XR writes Camera.fieldOfView from it each frame — measured by the reporter at 76.5°–124.5° against an authored 60°. A Screen Space - Camera canvas sizes itself from Camera.fieldOfView, so it fits itself to the tracking-derived value while the actual rendering uses the projection matrix. Hence both the constant over-scale and the movement with the viewer.

This is not the rig writing the FOV — the rig only reads it, and in fact already caches the authored value to avoid exactly this feedback loop (Runtime/DisplayXRCamera.cs:107,210). The write comes from Unity's XR layer because a projection is supplied.

The working answer today

Verified on hardware in a standalone player:

no rig + DisplayXRSceneMode(TwoD) + a full-rect DisplayXRWindowSpaceUI + the Samples~/WindowSpaceUI mouse router

DisplayXRWindowSpaceUI is a composition layer at a fixed window rect, so it is immune to the camera pose and projection entirely. This is now documented in docs~/architecture/two-dimensional-scenes.md (via #272).

What is actually open here

The docs now steer people to the working configuration, but the underlying sharp edge remains:

  1. Camera.fieldOfView is not the authored value while a session runs, and anything reading it (uGUI's Screen Space - Camera, third-party UI, gameplay code doing FOV math, cinematic tools) silently gets a tracking-derived number. Worth deciding whether the plugin can expose an "authored FOV" accessor, and whether the rig's existing cache should be public rather than each caller re-deriving it.
  2. A rig-less camera still receives head-tracked poses, which is surprising in exactly the same way No way to author a 2D scene: every camera renders stereo while the session runs, and the mode-switch API is undocumented #267 was. No way to author a 2D scene: every camera renders stereo while the session runs, and the mode-switch API is undocumented #267 solved the rendering mode; it did not give a way to opt a single camera out of tracking.

Neither has an obviously correct fix — a per-camera "ignore XR pose" opt-out cuts against how Unity's XR camera integration works. Filing so the sharp edge is tracked rather than rediscovered, and so the docs have something to point at.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions