OpenXR Eye-Gaze Interaction Works in Editor but Fails on Quest Build - Permission and Feature Group Fix
Problem: Eye-gaze interaction works in Unity Editor testing, but after deploying to Quest build the gaze ray never activates, gaze-driven UI focus does not trigger, or gaze input returns default values only.
Fastest safe fix path: In 2026, this is usually a build-lane parity issue, not a scene-logic issue. Android OpenXR feature groups, manifest capability declarations, and runtime permission state are not aligned with the interaction profile your project expects.
If you validate those three layers in order, the issue is usually resolved without rewriting gameplay scripts.
Why this spikes now in 2026
Quest release lanes in 2026 increasingly mix hand tracking, controller input, and optional gaze-based interaction in one build. Teams test in Editor with simulation paths that appear valid, then ship Android builds where one of these conditions differs:
- the Android target OpenXR feature set is missing eye-gaze support
- required capability declarations are absent or overridden by stale manifest templates
- runtime permission and privacy prompts are not accepted or are never surfaced
This creates a misleading symptom pattern: the scene is correct, interaction maps are correct, but gaze interaction remains disabled on device.
Direct answer
When OpenXR eye-gaze works in Editor but fails in Quest build, fix it with this sequence:
- verify Android OpenXR feature groups and interaction profile selection
- verify merged manifest capability and permission declarations
- verify runtime permission flow and headset-level interaction mode
- verify input action bindings for gaze path in the built player
- run clean install and smoke-test scene before full build validation
Do not skip merged-manifest inspection. Most unresolved cases are capability drift, not code bugs.
Who this affects
- Unity XR teams shipping to Quest with OpenXR
- teams migrating from controller-only to mixed controller-plus-gaze interactions
- teams upgrading Unity, XR plugin, or OpenXR package versions before release
Step 1 - Validate OpenXR feature groups on Android target only
Open Edit -> Project Settings -> XR Plug-in Management -> OpenXR and select Android target.
Confirm:
- OpenXR is enabled for Android build target
- eye-gaze interaction-related feature group is enabled for Android (not only in Editor assumptions)
- conflicting or unnecessary features are disabled to avoid capability drift
Why this matters: Editor-target features do not guarantee Android-target feature parity.
Verification checkpoint: The Android OpenXR feature list includes explicit eye-gaze support and matches your release lane configuration sheet.
Step 2 - Confirm interaction profile and action-map compatibility
In your input setup:
- verify eye-gaze action bindings exist in the action asset included in build scenes
- verify gaze actions are enabled in runtime startup path
- verify your interaction profile and expected control path match enabled OpenXR features
Common failure pattern: action maps are valid in project asset but never enabled in the player boot path after scene transition.
Verification checkpoint: Player logs show gaze action map enabled and bound control paths resolved.
Step 3 - Inspect merged Android manifest, not template assumptions
Do not trust only AndroidManifest.xml source files. Inspect merged output from the actual build.
Check for:
- required XR capability declarations for your eye-gaze path
- permission declarations required by your runtime features
- absence of stale override entries from old templates or plugins
If you use custom manifest overrides, diff merged manifest against Unity-managed baseline generated with the same package versions.
Verification checkpoint: Merged manifest contains expected declarations and no conflicting duplicates.
Step 4 - Verify runtime permission and headset privacy flow
On Quest device:
- install fresh build (avoid stale install assumptions)
- review app permission state
- accept runtime prompts related to gaze or eye-tracking paths when presented
- reboot headset once after permission mode changes if runtime state appears stale
If permission flow is skipped or denied, gaze interaction may silently fail while other input paths remain active.
Verification checkpoint: Permission state is granted and headset runtime mode supports your interaction path before app launch.
Step 5 - Add startup logging for first 10 seconds
Add lightweight logs (development build only):
- active interaction profiles
- action maps enabled
- first gaze sample timestamp
- fallback to controller-only mode markers
This quickly separates configuration failure from gameplay logic failure.
Verification checkpoint: Logs show gaze profile active and non-default gaze samples arriving during startup.
Step 6 - Test with minimal gaze smoke scene
Before full game scene:
- launch a minimal scene with one gaze-selectable UI target
- test gaze focus and selection events
- validate with and without controller present
If minimal scene fails, continue fixing platform configuration.
If minimal scene passes but full scene fails, inspect scene boot order and action-map lifecycle.
Verification checkpoint: Minimal gaze scene passes consistently across clean reinstall and restart.
Step 7 - Check plugin/version parity after upgrades
After Unity or package updates:
- revalidate XR Plug-in Management settings per target
- recheck OpenXR feature groups
- recheck manifest merge output
- rerun minimal gaze smoke scene
Version bumps frequently reset or reinterpret config defaults.
Verification checkpoint: Post-upgrade parity report shows unchanged required gaze configuration.
Alternative fixes for edge cases
- Remove duplicate XR bootstrap prefabs that reconfigure input at runtime.
- Ensure only one input initialization authority runs at startup.
- If permissions are granted but gaze remains null, test with a clean sample project to isolate project-local overrides.
- Reimport XR/OpenXR package dependencies when settings appear inconsistent after package migration.
Prevention checklist for release lanes
Add these rows to your release checklist:
- Android OpenXR feature group snapshot attached
- merged manifest capability check attached
- runtime permission state verified on target headset
- gaze smoke-scene pass result attached
- fallback behavior documented if gaze unavailable
This prevents repeat regressions in late submission windows.
Common mistakes to avoid
Mistake: Checking only Editor OpenXR configuration
Fix: Always verify Android target configuration explicitly.
Mistake: Trusting manifest template files without merged-output inspection
Fix: Validate merged manifest from the exact build artifact.
Mistake: Testing only full gameplay scene
Fix: Add a minimal gaze smoke scene to isolate platform-level issues quickly.
Mistake: Assuming granted permissions persist across all reinstall paths
Fix: Recheck permission state on clean install and after runtime mode changes.
Verification matrix
| Check | Pass signal | Fail signal | Action |
|---|---|---|---|
| Android OpenXR feature group | eye-gaze feature enabled | feature absent or wrong target | fix target-specific OpenXR config |
| Merged manifest | required capability present | capability missing or overridden | repair manifest source and rebuild |
| Runtime permission | permission granted | denied or prompt never handled | grant/reset permission and retest |
| Action-map startup | gaze map enabled | no gaze map or wrong map | fix startup input lifecycle |
| Smoke scene | gaze select event fires | no event or null sample | continue config isolation |
Related problems and links
- OpenXR Hand Tracking Works in Editor but Fails on Quest Build - Feature Group and Manifest Capability Fix
- OpenXR Interaction Profile Selects Wrong Input Mode on Quest Build - Fallback Order and Startup Route Fix
- Unity OpenXR Validation Failed on Quest 3 - XR Plugin and Feature Group Fix
- Unity XR Hands Jitter or Teleport in Quest Build - Tracking Origin and Update Phase Alignment Fix
- Unity Cloud Build Uses Wrong Scripting Define Symbols - Build Target Matrix and Pre-Export Validation Fix
- Official docs: Unity OpenXR, Meta Quest Unity documentation
FAQ
Why can eye-gaze work in Editor but fail only on Quest build
Editor and Quest standalone builds do not share identical runtime and capability constraints. Android OpenXR feature groups, merged manifest declarations, and permission state can diverge from Editor assumptions, which disables gaze paths on device.
Do I need a custom Android manifest to fix this
Not always. Start with Unity-managed manifest generation and verify merged output. Use custom manifest only when required, then revalidate merged result after every plugin or package change.
Should I enable every OpenXR feature to be safe
No. Over-enabling can introduce capability conflicts and harder validation paths. Enable only the features required by your interaction design and verify them per build target.
What should I do if permissions are granted but gaze is still null
Run the minimal gaze smoke scene and startup logging. If smoke scene fails, continue platform/config checks. If smoke scene passes but full scene fails, inspect action-map lifecycle and scene initialization order.
Bookmark this article for your Quest release checklist and share it with teammates who own XR configuration before build promotion.