Skip to content
Development
Skill

/hz-unity-meta-movement-sdk-retargeting

Set up and tweak Meta Movement SDK (MSDK) retargeting for a character model. Use this whenever the user wants to retarget a humanoid FBX/prefab for Meta Quest body tracking, generate a retargeting config, or hand-edit the resulting `<asset>.json` (fix known-joint mappings,

From plugin
meta-vr
17629 skills1 hook1 MCP
Install
$ npx -y skills add meta-quest/agentic-tools --skill hz-unity-meta-movement-sdk-retargeting --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hz-unity-meta-movement-sdk-retargeting

Context preview

The summary Claude sees to decide when to auto-load this skill.

Set up and tweak Meta Movement SDK (MSDK) retargeting for a character model. Use this whenever the user wants to retarget a humanoid FBX/prefab for Meta Quest body tracking, generate a retargeting config, or hand-edit the resulting `<asset>.json` (fix known-joint mappings,

SKILL.md

hz-unity-meta-movement-sdk-retargeting.SKILL.md
name: hz-unity-meta-movement-sdk-retargeting
license: Apache-2.0
description: Set up and tweak Meta Movement SDK (MSDK) retargeting for a character model. Use this whenever the user wants to retarget a humanoid FBX/prefab for Meta Quest body tracking, generate a retargeting config, or hand-edit the resulting `<asset>.json` (fix known-joint mappings, exclude joints from auto-mapping, rename target joints, adjust per-joint mapping weights, change a mapping behavior to twist/childAlignedTwist, edit T-pose values). The headless entry point is `Meta.XR.Movement.Editor.MSDKUtilityEditor.RunDefaultRetargetingSetup(GameObject asset)` — call it via Unity MCP first, then hand-edit if needed. **Skip** if the user is editing runtime retargeting code, the source `OVRSkeletonData.json`, or non-MSDK files.

MSDK Retargeting Config

Workflow: always start with the headless API

Don't hand-craft the JSON from scratch — the native side computes initial alignment, mappings, and T-pose data that would be tedious to write by hand. The right flow is:

1. **Generate the default config** by calling `Meta.XR.Movement.Editor.MSDKUtilityEditor.RunDefaultRetargetingSetup(GameObject asset, string customDataSourcePath = null)` via Unity MCP. This is the headless equivalent of clicking through the Retargeting Configuration Editor UI with all defaults (Next×3 → Validate → Done) and produces both artifacts:

  • `<asset>.json` — the retargeting config (this skill targets this file)
  • `<asset>-metadata.asset` — a small ScriptableObject linking the model to the JSON (rarely needs editing)

2. **Inspect the generated JSON** to verify joint mappings look right. 3. **Hand-edit only if needed** — the rest of this skill describes the JSON structure and the common tweaks.

The same `RunDefaultRetargetingSetup` API also backs the `Assets/Movement SDK/Body Tracking/Run Default Retargeting Setup` editor menu item, so a user who sees a project asset selected can trigger it from the menu too.

Calling it via Unity MCP

The Unity MCP `Unity_RunCommand` script runner can't see the `Meta.*` namespace from the wrapped harness; use reflection to invoke the public static method:

using UnityEngine;
using UnityEditor;

internal class CommandScript : IRunCommand
{
    public void Execute(ExecutionResult result)
    {
        var asset = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/MyChar/MyChar.fbx");
        if (asset == null) { result.LogError("asset not found"); return; }

        System.Type editorType = null;
        foreach (var asm in System.AppDomain.CurrentDomain.GetAssemblies())
        {
            var t = asm.GetType("Meta.XR.Movement.Editor.MSDKUtilityEditor");
            if (t != null) { editorType = t; break; }
        }
        var method = editorType.GetMethod("RunDefaultRetargetingSetup");
        try { method.Invoke(null, new object[] { asset, null }); }
        catch (System.Reflection.TargetInvocationException tie) {
            result.LogError("RunDefaultRetargetingSetup failed: " + tie.InnerException);
            return;
        }
        result.Log("done; config at " + AssetDatabase.GetAssetPath(asset).Replace(System.IO.Path.GetExtension(AssetDatabase.GetAssetPath(asset)), ".json"));
    }
}

Notes:

  • The harness wraps the script in `Unity.AI.Assistant.Agent.Dynamic.Extension.Editor`, so a top-level `using Meta.XR.Movement.Editor;` won't compile — reflection is the workaround.
  • Avoid `using System.Reflection;` at the top of the file (the harness's namespace wrap interacts badly with it). Use fully-qualified `System.Reflection.MethodInfo` etc. inline if you need the types.
  • `RunDefaultRetargetingSetup` is **non-destructive** — if a JSON already exists, it loads and re-runs the per-step replay; user-made `target.knownJoints` and `source.autoMappingJointData` edits survive (see the "Re-running setup" table at the bottom).
  • The asset must live under `Assets/` or in an embedded package. Calling on an immutable package asset via MCP can trigger Unity's "save changes to immutable package?" dialog and fail.

When to hand-edit the JSON

The defaults are usually 80–95% right. Common reasons to hand-edit afterwards:

  • The auto-detector picked the wrong bone for a known joint (e.g. `chest` mapped to a spine bone, or `wrist` mapped to a wrist-twist bone).
  • Source-side joints like `LeftHandPalm` or `*WristTwist` are bleeding into target hand mappings and causing jitter.
  • The model's bones use a non-standard naming convention (`mixamorig:Hips`, `bn_pelvis_C_001`) and you want to clean up the joint names.
  • You want to manually tune `weightPosition` / `weightRotation` for a specific joint, or change a mapping `behavior` to `twist` / `childAlignedTwist`.
  • Character floats above ground / penetrates floor (T-pose root height fix).

The JSON drives runtime retargeting. The same skeleton-name strings appear across many sections — **edit them all consistently** or the native loader will silently produce broken mappings.

Top-level layout

{
  "name": "<character name>",
  "config":  { version, coordinateSpace }
  "source":  { format, joints, manifestations, autoMappingJointData, knownJoints, hierarchy, tposeMin, tposeMax, tpose }
  "target":  { format, joints, knownJoints, hierarchy, tposeMin, tposeMax, tpose }
  "mapping": { min: { <targetJoint>: <mappingEntry> }, max: { ... } }
}
  • **`source`** — the Meta Quest body tracking skeleton (typically OVR FullBody, ~84 joints). Joint names are fixed (e.g. `LeftHandWrist`, `Hips`); usually leave alone.
  • **`target`** — the user's character rig. Joint names come from the model's bone hierarchy (e.g. `Left_Hand`, `Hips`, `Skeleton`).
  • **`mapping`** — for each *target* joint, a weighted list of *source* joints that drive it. `min` is for the smallest body scale, `max` for the largest. The retargeter blends between them at runtime based on the user's height.

Joint names: where the same string must appear

A joint name (e.g. `"Right_

Read more
Ships withmeta-vr

Agentic skills and tools for Meta Quest and Horizon OS development.

Get the whole plugin