hz-unity-face-tracking

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Unity Face Tracking for ARKit-Rigged Models (Meta Movement SDK)

适用于ARKit绑定模型的Unity面部追踪方案(Meta Movement SDK)

End-to-end recipe to make a head/face model rigged with the standard 52 ARKit blendshapes animate from the wearer's face on Quest. 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.
本教程提供端到端方案,让采用标准52个ARKit blendshape绑定的头部/面部模型,能够根据Quest佩戴者的面部表情实现动画。使用公开的
OVRCustomFace
扩展钩子——无需
OVR_INTERNAL_CODE
,可交付给第三方。
模型的blendshape名称必须遵循ARKit命名规范(驼峰式命名,后缀为
_L
/
_R
,例如
eyeBlink_L
、
jawOpen
、
mouthSmile_R
)。类似
blendShape2.eyeBlink_L
的可选前缀会被自动去除。

When to use

适用场景

  • User has an FBX/GLB/mesh with ARKit-named blendshapes and wants it driven by Quest face tracking.
  • User asks: "animate this head with my face", "drive these blendshapes from face tracking", "use Movement SDK A2E with my model", "wire ARKit shapes to Quest".
  • Target device: Quest Pro, Quest 3, Quest 3S (Quest 2 is no-op — no face cameras).
  • 用户拥有带有ARKit命名blendshape的FBX/GLB/网格模型,希望通过Quest面部追踪驱动其动画。
  • 用户提出如下需求:“用我的面部表情驱动这个头部模型”、“通过面部追踪驱动这些blendshape”、“将Movement SDK A2E与我的模型结合使用”、“将ARKit形状与Quest关联”。
  • 目标设备:Quest Pro、Quest 3、Quest 3S(Quest 2无面部摄像头,无法实现该功能)。

Prerequisites checklist

前置条件清单

  1. Quest face tracking-capable headset (Pro / 3 / 3S).
  2. Packages in
    Packages/manifest.json
    :
    • com.meta.xr.sdk.core
      (Meta XR Core — provides
      OVRFaceExpressions
      ,
      OVRCustomFace
      )
    • com.meta.xr.sdk.movement
      (Meta Movement SDK — A2E + retargeting helpers)
  3. Assets/Oculus/OculusProjectConfig.asset
    (verify via Project Settings → Meta XR):
    • faceTrackingSupport: 1
      (Supported) or
      2
      (Required)
    • eyeTrackingSupport: 1
      if the rig has gaze
  4. Android manifest (
    Assets/Plugins/Android/AndroidManifest.xml
    ) permissions:
    • <uses-feature android:name="oculus.software.face_tracking" android:required="false" />
    • <uses-permission android:name="com.oculus.permission.FACE_TRACKING" />
    • <uses-permission android:name="android.permission.RECORD_AUDIO" />
      (required for A2E)
    • For eye gaze:
      oculus.software.eye_tracking
      +
      com.oculus.permission.EYE_TRACKING
  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, call
meta_update_android_manifest
to regenerate the manifest.
  1. 支持面部追踪的Quest头显(Pro/3/3S)。
  2. Packages/manifest.json
    中的依赖包
    :
    • com.meta.xr.sdk.core
      (Meta XR Core——提供
      OVRFaceExpressions
      、
      OVRCustomFace
      )
    • com.meta.xr.sdk.movement
      (Meta Movement SDK——包含A2E和重定向工具)
  3. Assets/Oculus/OculusProjectConfig.asset
    (可通过Project Settings → Meta XR验证):
    • faceTrackingSupport: 1
      (支持)或
      2
      (必需)
    • 如果模型包含视线追踪,需设置
      eyeTrackingSupport: 1
  4. Android清单文件(
    Assets/Plugins/Android/AndroidManifest.xml
    )权限:
    • <uses-feature android:name="oculus.software.face_tracking" android:required="false" />
    • <uses-permission android:name="com.oculus.permission.FACE_TRACKING" />
    • <uses-permission android:name="android.permission.RECORD_AUDIO" />
      (A2E必需)
    • 视线追踪需添加:
      oculus.software.eye_tracking
      +
      com.oculus.permission.EYE_TRACKING
  5. 场景中的OVRCameraRig需在
    OVRManager.FaceTrackingDataSources
    中包含
    Audio
    (A2E)——若跳过Audio,嘴部动作仅为视觉驱动。
修改OculusProjectConfig后,调用
meta_update_android_manifest
重新生成清单文件。

Approach (high level)

整体流程(概览)

  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 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.
  1. 将**
    ARKitOVRCustomFace
    **脚本(位于
    references/ARKitOVRCustomFace.cs
    )导入项目。
  2. 为OVRCameraRig(或场景中任意对象)添加
    OVRFaceExpressions
    组件。
  3. 在带有模型
    SkinnedMeshRenderer
    的GameObject上添加
    ARKitOVRCustomFace
    组件。添加组件时会触发
    Reset()
    方法,通过扫描网格的blendshape名称自动填充blendshape→FaceExpression映射关系。
  4. 将组件的
    FaceExpressions
    字段关联到
    OVRFaceExpressions
    实例。
  5. 如需视线追踪:导入**
    ARKitEyeGazeBlendshapeDriver
    **(详见下方视线追踪部分)。
  6. 通过Meta XR Link运行Play模式,或构建APK并侧载到设备。首次启动时,接受面部追踪/视线追踪/麦克风权限请求。
以上就是完整流程,详细说明如下。

Eye tracking (DO THIS — face expressions alone don't work)

视线追踪(必须配置——仅面部表情无法实现完整功能)

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
:
  • Reads gaze rotation from two
    OVREyeGaze
    components (one per eye,
    TrackingMode = HeadSpace
    ).
  • Computes rotation relative to a head reference (e.g.
    CenterEyeAnchor
    ).
  • Decomposes pitch →
    eyeLookUp/Down_{L,R}
    , yaw →
    eyeLookIn/Out_{L,R}
    (with the ARKit "_In = toward nose" convention).
  • Writes weights in
    LateUpdate
    , so it overrides whatever
    ARKitOVRCustomFace
    wrote in
    Update
    .
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.
请勿依赖
OVRFaceExpressions.EyesLook*
实现视线追踪
。这些字段由面部摄像头视觉数据推导而来,而非专用的眼球追踪器。在Quest Pro上,即便面部追踪正常工作,这些字段的值也常为0或存在噪声。正确的API是
OVREyeGaze
,它直接调用眼球追踪器。
对于带有
eyeLook*
blendshape(无眼球骨骼)的ARKit绑定模型,本方案提供**
ARKitEyeGazeBlendshapeDriver
**:
  • 从两个
    OVREyeGaze
    组件(双眼各一个,
    TrackingMode = HeadSpace
    )读取视线旋转数据。
  • 计算相对于头部参考对象(例如
    CenterEyeAnchor
    )的旋转角度。
  • 将旋转分解为俯仰角→
    eyeLookUp/Down_{L,R}
    ,偏航角→
    eyeLookIn/Out_{L,R}
    (遵循ARKit“_In = 朝向鼻子”的约定)。
  • 在
    LateUpdate
    中写入权重,覆盖
    ARKitOVRCustomFace
    在
    Update
    中写入的值。
对于带有眼球骨骼(无
eyeLook*
blendshape)的模型,无需分解blendshape,只需将
OVREyeGaze
作为子对象添加到每个眼球骨骼,并设置
ApplyRotation = true
——组件会直接旋转骨骼。

Eye gaze setup (blendshape rigs)

视线追踪设置(Blendshape绑定模型)

  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.
  1. 在
    CenterEyeAnchor
    (或你的头部变换对象)下创建两个空GameObject:
    LeftEyeGaze
    、
    RightEyeGaze
    。
  2. 为每个对象添加
    OVREyeGaze
    组件。设置
    Eye = Left
    /
    Right
    ,
    TrackingMode = HeadSpace
    ,
    ApplyPosition = false
    ,
    ApplyRotation = true
    ,
    ConfidenceThreshold = 0.5
    。
  3. 为头部的SkinnedMeshRenderer GameObject添加
    ARKitEyeGazeBlendshapeDriver
    组件(与
    ARKitOVRCustomFace
    共存)。关联
    leftEye
    、
    rightEye
    和
    referenceFrame
    (即
    CenterEyeAnchor
    )。
  4. 根据需求调整
    maxAngleDeg
    (默认30°)和
    smoothing
    (默认0.4)参数。

Step-by-step

分步指南

1. Install the script

1. 安装脚本

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).
将
references/ARKitOVRCustomFace.cs
复制到
Assets/Scripts/ARKitOVRCustomFace.cs
。该脚本定义了公开的、可交付给第三方的ARKit ↔ OVR FaceExpression映射表,以及
MapBlendshapes()
方法——该方法会扫描
SkinnedMeshRenderer.sharedMesh.GetBlendShapeName(i)
,去除最后一个
.
之前的所有前缀,转换为小写后与映射表匹配。未匹配的网格blendshape会被设置为
OVRFaceExpressions.FaceExpression.Max
(标记值——运行时会跳过)。

2. Enable Movement SDK + permissions

2. 启用Movement SDK及权限

Project settings:
Project Settings → Meta XR → Face Tracking Support = Supported
Project Settings → Meta XR → Eye Tracking Support = Supported (if needed)
Then regenerate manifest:
  • Unity MCP:
    meta_update_android_manifest
  • Or Editor menu: Meta → Tools → Update AndroidManifest.xml
项目设置:
Project Settings → Meta XR → Face Tracking Support = Supported
Project Settings → Meta XR → Eye Tracking Support = Supported(如需视线追踪)
然后重新生成清单文件:
  • Unity MCP:执行
    meta_update_android_manifest
  • 或通过编辑器菜单:Meta → Tools → Update AndroidManifest.xml

3. Scene setup

3. 场景设置

Scene Hierarchy
├── OVRCameraRig                         (from meta_add_camerarig)
│   └── (add) OVRFaceExpressions         component
└── YourHeadModel
    └── ...SkinnedMeshRenderer GO...
        ├── SkinnedMeshRenderer          (existing)
        └── (add) ARKitOVRCustomFace     component
             └── FaceExpressions = the OVRFaceExpressions ref
             └── retargetingType = Custom (set automatically by base when overriding)
             └── Mappings[] = auto-filled on Reset()
             └── BlendShapeStrengthMultiplier = 100 (default; OVR weights are 0–1, mesh wants 0–100)
If the head has multiple
SkinnedMeshRenderer
s (e.g. separate teeth/tongue meshes), add
ARKitOVRCustomFace
to each one.
场景层级
├── OVRCameraRig                         (来自meta_add_camerarig)
│   └── (添加) OVRFaceExpressions         组件
└── YourHeadModel
    └── ...带有SkinnedMeshRenderer的GameObject...
        ├── SkinnedMeshRenderer          (已存在)
        └── (添加) ARKitOVRCustomFace     组件
             └── FaceExpressions = 关联OVRFaceExpressions实例
             └── retargetingType = Custom (重写时由基类自动设置)
             └── Mappings[] = 重置时自动填充
             └── BlendShapeStrengthMultiplier = 100 (默认值;OVR权重范围0–1,网格权重范围0–100)
如果头部模型包含多个
SkinnedMeshRenderer
(例如牙齿/舌头为独立网格),需为每个
SkinnedMeshRenderer
添加
ARKitOVRCustomFace
组件。

4. OVRManager — enable Audio as a data source (A2E)

4. OVRManager——启用Audio作为数据源(A2E)

On
OVRCameraRig
's OVRManager component:
  • Face Tracking Data Sources → check Visual AND Audio (Audio = A2E; produces mouth shapes from microphone when the visual face cameras can't see something — talking, occlusion, etc.).
在
OVRCameraRig
的OVRManager组件中:
  • Face Tracking Data Sources → 勾选Visual和Audio(Audio即A2E;当面部摄像头无法捕捉到动作时——如说话、遮挡等,通过麦克风生成嘴部形状)。

5. Trigger the mapping if the component already existed

5. 若组件已存在,触发映射操作

MapBlendshapes()
runs automatically when the component is added (
Reset()
) and from
OnValidate()
when
Mappings
is empty. If you need to remap manually (e.g. after re-importing the FBX), use the component's inspector context menu → Map Blendshapes, or from a script:
csharp
go.GetComponent<ARKitOVRCustomFace>().MapBlendshapes();
From Unity MCP
Unity_RunCommand
, the cleanest invocation (the OVR/MSDK types aren't referenced in the MCP dynamic assembly, so use SendMessage to avoid reflection):
csharp
GameObject.Find("YourHeadModel")
    .GetComponentInChildren<SkinnedMeshRenderer>().gameObject
    .SendMessage("MapBlendshapes", SendMessageOptions.RequireReceiver);
MapBlendshapes()
会在组件添加时自动运行(
Reset()
),并在
Mappings
为空时通过
OnValidate()
运行。如需手动重新映射(例如重新导入FBX后),可使用组件的检查器上下文菜单 → Map Blendshapes,或通过脚本调用:
csharp
go.GetComponent<ARKitOVRCustomFace>().MapBlendshapes();
在Unity MCP
Unity_RunCommand
中,最简洁的调用方式(OVR/MSDK类型未在MCP动态程序集中引用,因此使用SendMessage避免反射):
csharp
GameObject.Find("YourHeadModel")
    .GetComponentInChildren<SkinnedMeshRenderer>().gameObject
    .SendMessage("MapBlendshapes", SendMessageOptions.RequireReceiver);

6. Verify

6. 验证

  • In Editor, with Meta XR Link / Quest Link, enter Play mode and make faces. The model should mirror them.
  • On device, build APK, side-load, grant Face Tracking + Microphone permissions on first launch.
  • Check the mapping at edit time: inspect the
    ARKitOVRCustomFace
    component.
    Mappings.Length
    should equal
    SkinnedMeshRenderer.sharedMesh.blendShapeCount
    . The Console log from
    MapBlendshapes()
    reports
    mapped X/N blendshapes
    — X should be 50 (or 52 if the FBX has all of them).
  • 编辑器中:通过Meta XR Link / Quest Link进入Play模式,做出面部表情,模型应同步镜像表情。
  • 设备上:构建APK并侧载,首次启动时授予面部追踪+麦克风权限。
  • 编辑时检查映射:查看
    ARKitOVRCustomFace
    组件。
    Mappings.Length
    应等于
    SkinnedMeshRenderer.sharedMesh.blendShapeCount
    。
    MapBlendshapes()
    的控制台日志会显示
    mapped X/N blendshapes
    ——X应为50(若FBX包含全部52个则为52)。

Troubleshooting

故障排查

SymptomCause / fix
mapped 0/N
in Console
Mesh blendshape names don't follow ARKit convention. Verify with
mesh.GetBlendShapeName(i)
. Names must match e.g.
eyeBlink_L
,
jawOpen
— case-insensitive, prefix before last
.
is stripped.
Face is frozen
OVRFaceExpressions
not assigned, or scene has no
OVRCameraRig
/
OVRManager
with face tracking enabled. Check
OVRFaceExpressions.FaceTrackingEnabled
and
ValidExpressions
at runtime.
Mouth doesn't move when speakingA2E disabled. Enable Audio under
OVRManager → Face Tracking Data Sources
, and ensure
RECORD_AUDIO
permission is granted on device.
Eyes don't blinkMesh's eyelid shapes aren't named
eyeBlink_L
/
_R
. Either rename, or add a custom row to
ARKitTable
.
Eyes don't move (look around)You're relying on
OVRFaceExpressions.EyesLook*
instead of
OVREyeGaze
— switch to
ARKitEyeGazeBlendshapeDriver
.
Eye gaze in wrong directionNote the deliberate ARKit ↔ OVR swap: ARKit's
eyeLookIn_L
(eye looking nose-ward, i.e. right) maps to OVR
EyesLookRightL
. The table already does this — don't "fix" it.
Weights look half-strength or clamped
BlendShapeStrengthMultiplier
defaults to 100 because Unity blendshapes are 0–100 while OVR is 0–1. Don't lower this unless intentional.
cannot change access modifiers when overriding
compile error
Base method is
protected internal
in another assembly. The override must use
protected
(not
protected internal
) — already correct in the supplied script.
_mappings out of sync with shared mesh
assertion at Start
Mesh changed since mapping was generated. Re-run
MapBlendshapes()
via the component context menu.
症状原因/修复方案
控制台显示
mapped 0/N
网格blendshape名称不符合ARKit规范。通过
mesh.GetBlendShapeName(i)
验证名称。名称需匹配例如
eyeBlink_L
、
jawOpen
——不区分大小写,最后一个
.
之前的前缀会被去除。
面部模型静止不动未关联
OVRFaceExpressions
,或场景中无启用面部追踪的
OVRCameraRig
/
OVRManager
。运行时检查
OVRFaceExpressions.FaceTrackingEnabled
和
ValidExpressions
。
说话时嘴部无动作A2E未启用。在
OVRManager → Face Tracking Data Sources
中启用Audio,并确保设备已授予
RECORD_AUDIO
权限。
眼睛不眨眼模型的眼睑blendshape名称不是
eyeBlink_L
/
_R
。可修改名称,或在
ARKitTable
中添加自定义条目。
眼睛无法转动(环顾四周)依赖
OVRFaceExpressions.EyesLook*
而非
OVREyeGaze
——切换为
ARKitEyeGazeBlendshapeDriver
。
视线方向错误注意ARKit与OVR的语义故意互换:ARKit的
eyeLookIn_L
(眼睛朝向鼻子,即向右看)对应OVR的
EyesLookRightL
。映射表已处理该逻辑——请勿“修正”。
权重强度减半或被限制
BlendShapeStrengthMultiplier
默认值为100,因为Unity blendshape权重范围是0–100,而OVR是0–1。除非有意调整,否则请勿降低该值。
编译错误
cannot change access modifiers when overriding
基类方法在其他程序集中为
protected internal
。重写时必须使用
protected
(而非
protected internal
)——提供的脚本已正确设置。
启动时断言
_mappings out of sync with shared mesh
映射生成后网格已更改。通过组件上下文菜单重新运行
MapBlendshapes()
。

ARKit ↔ OVR FaceExpression mapping (reference)

ARKit ↔ OVR FaceExpression映射参考

The 52 ARKit shapes don't 1:1 a FACS-based OVR enum. Notable choices baked into
ARKitTable
:
  • Centrally-named ARKit shapes that have L+R OVR pairs (
    browInnerUp
    ,
    cheekPuff
    ,
    mouthFunnel
    ,
    mouthPucker
    ,
    mouthRollLower
    ,
    mouthRollUpper
    ) pick only the L-side OVR expression. If your model has obviously asymmetric mouth/brow when the user uses these expressions and you want true symmetric drive, subclass and additively sum L+R in a custom
    MapBlendshapes
    (use
    SlothARKitFaceDriver
    -style per-blendshape sum). For most heads the L-only choice is fine because the face is roughly symmetric and the asymmetry is below visual threshold.
  • eyeLookIn/Out
    are deliberately swapped per side relative to OVR's left/right semantics (see Troubleshooting).
  • mouthClose
    →
    LipsToward
    (closest FACS analogue).
  • tongueOut
    →
    TongueOut
    (requires HorizonOS ≥ 65 + tongue tracking; otherwise stays at 0).
52个ARKit形状与基于FACS的OVR枚举并非一一对应。
ARKitTable
中包含以下关键映射规则:
  • ARKit的中央命名形状对应OVR的左右成对形状(
    browInnerUp
    、
    cheekPuff
    、
    mouthFunnel
    、
    mouthPucker
    、
    mouthRollLower
    、
    mouthRollUpper
    )仅选择左侧OVR表情。若用户做出这些表情时模型的嘴部/眉毛明显不对称,且需要真正的对称驱动,可创建子类并在自定义
    MapBlendshapes
    中累加左右侧值(参考
    SlothARKitFaceDriver
    的逐blendshape累加方式)。对于大多数头部模型,仅使用左侧的选择已足够,因为面部大致对称,不对称性低于视觉阈值。
  • **
    eyeLookIn/Out
    **的左右侧语义与OVR故意互换(详见故障排查)。
  • mouthClose
    →
    LipsToward
    (最接近的FACS对应项)。
  • tongueOut
    →
    TongueOut
    (要求HorizonOS ≥ 65 + 舌头追踪;否则保持为0)。

Files in this skill

本方案包含的文件

  • SKILL.md
    — this file
  • references/ARKitOVRCustomFace.cs
    — drop-in
    OVRCustomFace
    subclass
  • references/ARKitEyeGazeBlendshapeDriver.cs
    — OVREyeGaze →
    eyeLook*
    blendshape driver (LateUpdate)
  • SKILL.md
    — 本文档
  • references/ARKitOVRCustomFace.cs
    — 可直接导入的
    OVRCustomFace
    子类
  • references/ARKitEyeGazeBlendshapeDriver.cs
    — OVREyeGaze →
    eyeLook*
    blendshape驱动脚本(LateUpdate)

Why this approach (vs. alternatives)

本方案的优势(对比其他方案)

  • Custom
    MonoBehaviour
    driver
    that reads
    OVRFaceExpressions[expr]
    and writes blendshape weights directly: works, but doesn't integrate with MSDK's correctives, eye constraints, or future retargeting upgrades. Use only if you can't extend
    OVRCustomFace
    .
  • OVRCustomFace
    +
    RetargetingType.ARKitBlendshapes
    : clean, but guarded behind
    #if OVR_INTERNAL_CODE
    in the public Oculus Integration package — not 3P-shippable.
  • OVRCustomFace
    +
    RetargetingType.Custom
    +
    GetCustomBlendShapeNameAndExpressionPairs
    override
    (this skill): fully public API, shippable, and gets all base-class behavior (data validity gating, weight scaling, mesh assertion).
  • 自定义MonoBehaviour驱动脚本:读取
    OVRFaceExpressions[expr]
    并直接写入blendshape权重——可行,但无法集成MSDK的修正、眼球约束或未来的重定向升级。仅当无法扩展
    OVRCustomFace
    时使用。
  • OVRCustomFace
    +
    RetargetingType.ARKitBlendshapes
    :简洁,但在公开Oculus Integration包中被
    #if OVR_INTERNAL_CODE
    保护——无法交付给第三方。
  • OVRCustomFace
    +
    RetargetingType.Custom
    + 重写
    GetCustomBlendShapeNameAndExpressionPairs
    (本方案):完全基于公开API,可交付,且具备所有基类行为(数据有效性校验、权重缩放、网格断言)。