hz-android-2d-porting
Guides porting existing Android 2D apps to Meta VR and Horizon OS — input adaptation, panel layout, and design requirements. Use…
Drive ARKit-blendshape-rigged head/face models in Unity with the wearer's facial expressions on Meta VR via Meta Movement SDK (face tracking + A2E). Use when a user has an FBX with the 52 ARKit blendshapes (any prefix, _L/_R suffixes) and wants it to animate from face tracking
Claude Code
$ npx -y skills add meta-quest/agentic-tools --skill hz-unity-face-tracking --agent claude-code
Codex
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a codex -y
Cursor
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a cursor -y
Gemini CLI
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a gemini-cli -y
GitHub Copilot
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a github-copilot -y
OpenCode
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a opencode -y
Windsurf
$ npx skills add meta-quest/agentic-tools --skill hz-unity-face-tracking -a windsurf -y
name: hz-unity-face-tracking license: Apache-2.0 description: Drive ARKit-blendshape-rigged head/face models in Unity with the wearer's facial expressions on Meta VR via Meta Movement SDK (face tracking + A2E). Use when a user has an FBX with the 52 ARKit blendshapes (any prefix, _L/_R suffixes) and wants it to animate from face tracking on Quest Pro / Quest 3 / Quest 3S.
End-to-end recipe to make a head/face model rigged with the standard 52 ARKit blendshapes animate from the wearer's face on Meta VR. Uses the **public** `OVRCustomFace` extension hook — no `OVR_INTERNAL_CODE`, ships to 3P.
The model's blendshape names must follow the ARKit naming convention (camelCase, `_L`/`_R` suffixes, e.g. `eyeBlink_L`, `jawOpen`, `mouthSmile_R`). An optional prefix like `blendShape2.eyeBlink_L` is automatically stripped.
1. **Quest face tracking-capable headset** (Pro / 3 / 3S). 2. **Packages** in `Packages/manifest.json`:
3. **`Assets/Oculus/OculusProjectConfig.asset`** (verify via Project Settings → Meta XR):
4. **Android manifest** (`Assets/Plugins/Android/AndroidManifest.xml`) permissions:
5. **OVRCameraRig** in the scene with `OVRManager.FaceTrackingDataSources` including `Audio` (A2E) — if you skip Audio, mouth motion is visual-only.
After any change to OculusProjectConfig, regenerate the manifest (see [Regenerating the manifest](#regenerating-the-manifest) below).
1. Drop the **`ARKitOVRCustomFace`** script (in `references/ARKitOVRCustomFace.cs`) into the project. 2. Add an `OVRFaceExpressions` component to the OVRCameraRig (or anywhere in the scene). 3. On the GameObject that has the model's `SkinnedMeshRenderer`, add `ARKitOVRCustomFace`. Adding the component triggers `Reset()`, which auto-populates the blendshape→FaceExpression mapping by scanning the mesh's blendshape names. 4. Wire the component's `FaceExpressions` field to the `OVRFaceExpressions` instance. 5. For eye gaze: drop **`ARKitEyeGazeBlendshapeDriver`** in (see [Eye tracking](#eye-tracking-do-this--face-expressions-alone-dont-work) below). 6. Press Play with Meta XR Link, or build APK and side-load. On first launch, accept the Face Tracking / Eye Tracking / Microphone permission prompts.
That's the whole flow. Details below.
**Don't rely on `OVRFaceExpressions.EyesLook*` for eye gaze.** Those fields are derived from face-camera visuals, not the dedicated eye tracker. On Quest Pro they're often zero or noisy even when face tracking is otherwise working. The right API is `OVREyeGaze`, which taps the eye tracker directly.
For ARKit rigs with `eyeLook*` blendshapes (no eye bones), this skill ships **`ARKitEyeGazeBlendshapeDriver`**:
For rigs with **eye bones** (no `eyeLook*` blendshapes), skip the blendshape decomposition and just parent `OVREyeGaze` to each eye bone with `ApplyRotation = true` — the component will rotate the bone directly.
1. Create two empty GameObjects under `CenterEyeAnchor` (or your head transform): `LeftEyeGaze`, `RightEyeGaze`. 2. Add `OVREyeGaze` to each. Set `Eye = Left` / `Right`, `TrackingMode = HeadSpace`, `ApplyPosition = false`, `ApplyRotation = true`, `ConfidenceThreshold = 0.5`. 3. Add `ARKitEyeGazeBlendshapeDriver` to the head's SkinnedMeshRenderer GameObject (alongside `ARKitOVRCustomFace`). Wire `leftEye`, `rightEye`, and `referenceFrame` (= `CenterEyeAnchor`). 4. Tweak `maxAngleDeg` (default 30°) and `smoothing` (default 0.4) to taste.
Copy `references/ARKitOVRCustomFace.cs` into `Assets/Scripts/ARKitOVRCustomFace.cs`. It defines the public, 3P-shippable ARKit ↔ OVR FaceExpression table and a `MapBlendshapes()` method that scans `SkinnedMeshRenderer.sharedMesh.GetBlendShapeName(i)`, strips any prefix before the last `.`, lowercases, and matches against the table. Unmatched mesh blendshapes are set to `OVRFaceExpressions.FaceExpression.Max` (sentinel — skipped at runtime).
Project settings:
Project Settings → Meta XR → Face Tracking Support = Supported Project Settings → Meta XR → Eye Tracking Support = Supported (if needed)
Then regenerate the manifest.
Against a live Editor, call the SDK's generator through `run_script` — the type resolves directly, so no reflection is needed:
// AgentScripts/UpdateManifest.cs
public static class UpdateManifest
{Guides porting existing Android 2D apps to Meta VR and Horizon OS — input adaptation, panel layout, and design requirements. Use…
Upgrades Meta VR apps to newer Horizon OS SDK versions — migration guides, deprecated API replacements, changelog. Use when…
Guides design of comfortable, intuitive VR/MR experiences for Meta VR and Horizon OS — comfort guidelines, interaction patterns,…
Builds WebXR experiences for Meta VR and Horizon OS using the Immersive Web SDK (IWSDK) — ECS architecture, Three.js integration,…
Build multi-window Meta Horizon OS experiences with the MetaVrx Layout SDK in Jetpack Compose or React Native. Covers framework…
Builds app UI for Meta VR and Horizon OS with the MetaVrx UI Set, a Jetpack Compose component library and design system. Covers…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.