Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Unity 6000.3 animation profile

Use this page when FBX animation will be imported by Unity 6.3 LTS. AnimSmith has a current Unity Generic root-motion profile plus the preserved Humanoid profile:

Rig pathExact tuple
Genericunity-generic / revision 2 / 6000.3 / fbx-model-importer
Humanoidunity-humanoid / revision 1 / 6000.3 / fbx-model-importer

These are importer contracts, not claims that every Unity 6000.3 project uses the same rig, controller, physics setup, or root-motion policy. Both accept FBX only. Revision 2 is the exact Generic contract used by the engine-root-motion prediction; revision 1 remains readable for historical advice artifacts. An engine profile never changes AnimSmith measurements.

What Unity expects

Unity's Rig tab maps a Generic rig through a chosen root node and a Humanoid rig through an Avatar. Its Animation tab defines clip ranges, loops, and whether rotation, vertical position, and XZ position are baked into the pose or extracted as root motion. A clean source therefore still needs an intentional rig type, Avatar/root selection, clip cuts, movement ownership, and controller setup.

The Model tab documents three separate scale influences: source-file scale, Scale Factor, and Transform scale. The preserved revision-1 advice profile models Convert Units and Bake Axis Conversion; Generic revision 2 deliberately does not claim either setting. It models only the closed animation/root-motion controls listed below, not Scale Factor, Avatar construction, or the imported hierarchy that Unity ultimately creates.

AnimSmith checks and thresholds

The ordinary mechanical and contract-aware catalog runs unchanged under either Unity profile. The most importer-sensitive rows are:

Check idExact default boundaryWhy it matters in Unity
rest-world-scaleselected node factor 1.0, inclusive tolerance 0.0001Finds inherited scale at sockets, IK targets, and attachment nodes before import.
scale-keyscomponent range greater than 1e-4Flags animated scale that may complicate retargeting and attachments.
non-uniform-scalerelative component spread greater than 1e-4Identifies non-uniform scale before Avatar/Transform composition.
constant-nonunit-scaleunit deviation greater than 1e-4; off by defaultOpt in when the project forbids retained constant scale channels.
in-placemeasured XZ root speed at least 0.5 m/s counts as travellingCross-checks declared gameplay-owned versus animation-owned XZ motion.
loop-closure0.01 m position and 1.0° rotationChecks declared loops before Unity's Loop Pose processing.
loop-seam-vel / loop-seam-rot0.1 m/s / 5.0°/sFinds velocity discontinuities that matching endpoint poses can hide.

The current Unity-only check is engine-root-motion, and it is applicable only for the exact Generic revision-2 tuple, an FBX source, and declared movement ownership. engine-addressability remains a Bevy-only rule. The separate generate import-advice contract still projects only settings declared under the historical revision-1 Unity advice profile.

The ownership line is explicit: #267 provides the parent/rest-world/bind scale measurements, #268 provides the selected-node rest-world-scale finding, and #155 provides the Unity importer suggestion document. Static placement baking (#224) and skinned rest/bind reparameterization (#269) are different repair domains.

Configure the exact importer contract

Every applicable revision-2 setting is required; the profile does not invent a default. The exact Generic root-motion tuple is:

[engine]
profile = "unity-generic"
profile_revision = 2
engine_version = "6000.3"
importer = "fbx-model-importer"

[engine.settings]
animation_type = "generic"
avatar_setup = "create_from_this_model"
import_animation = true
root_motion_source = "Reference/Root"

[clips."*".engine_settings]
root_rotation = "extract"
root_position_y = "bake"
root_position_xz = "extract"

[runtime_nodes]
selectors = ["weapon_socket", "ik_*_target"]

[checks.rest-world-scale]
expected_uniform_scale = 1.0
uniform_scale_tolerance = 0.0001

For Humanoid, select the preserved unity-humanoid revision-1 profile and omit root_motion_source; that setting is not applicable to the Humanoid profile. Generic revision 2 freezes animation_type = "generic", avatar_setup = "create_from_this_model", and import_animation = true; other values are rejected. The three clip-scoped bake or extract choices are required for every actual Generic clip. The example above is a prediction configuration, not a Unity project file.

Root-motion prediction

engine-root-motion compares one declared movement owner with one materialized Unity clip setting for each declared axis: horizontal_xz uses root_position_xz, vertical_y uses root_position_y, and yaw uses root_rotation. bake means baked_into_pose; extract means stored_as_root_motion. Gameplay ownership is compatible with baking, while animation ownership is compatible with extraction. A conflict is an ordinary error finding with a prediction_scope, not a rewritten measurement or an automatic fix.

The check's lifecycle is explicit. A selected, enabled, applicable check emits one available facet per clip/axis when all evidence is present. Its machine result is RootMotionRouting with project_owner, importer_disposition, and compatibility. A clip with no declared axis is not applicable for that axis. Missing raw-path coverage, incomplete project intent, duplicate/overflowed settings, a missing or ambiguous source path, a path that does not identify the resolved Root role, or unavailable axis-specific trajectory evidence emits a required_prediction_unavailable facet instead. Required-unavailable work is not a content finding, cannot be suppressed with --allow, makes the check not_evaluated when all work is unavailable (or partial when mixed), and makes lint exit 1.

Project-intent construction is bounded at each retained source/declaration prefix plus one overflow witness. An unmapped declaration tail is therefore not silently treated as ownerless: NPlusOne intent work makes the exact profile unavailable and produces one atomic summary. A complete, exhaustively observed source/intent inventory with no declared owner remains genuinely not applicable; path evidence is required once declared work exists.

The source path must resolve to the explicitly resolved Root role. This rule does not use the consumer-neutral Hips fallback: a resolved Hips role cannot stand in for a missing Root. Root trajectory measurements may be unavailable for an individual axis, but their numeric magnitude is never an applicability or routing threshold. A zero-travel clip and a travelling clip use the same ownership/setting comparison when their required measurement availability is measured.

Closed raw FBX path evidence

root_motion_source is a case-sensitive, byte-exact relative transform path. The V1 grammar uses / as its only separator and has no escaping or Unicode normalization. Paths must have nonempty segments; leading/trailing /, //, . and .. segments, backslashes, control or Unicode format characters are rejected. A segment is at most 1,024 UTF-8 bytes, a complete path at most 4,096 bytes, and a path at most 256 segments.

The FBX loader projects this path inventory from the same input bytes through a raw-preserving ufbx load. Original source node identities, parent chains, and names are retained; the implicit ufbx root and generated geometry/scale helper nodes remain evidence but cannot satisfy a configured path. Complete coverage is required to prove NoMatch; incomplete or unavailable coverage produces CoverageIncomplete, never a guessed absence. This is raw-source evidence, not a claim that Unity executed the import.

Generate the bounded advice document with the historical advice profile using:

animsmith --config unity.animsmith.toml generate import-advice character.fbx

The result maps the declared values to Unity importer properties. It does not assert that Unity imported successfully or that the imported motion matches the source visually. The root-motion prediction likewise performs no Unity editor execution, imported-asset readback, runtime playback, or engine certification. Repository and CI evidence for this slice uses only self-authored synthetic FBX fixtures; commercial animation packs are not fixtures or uploaded artifacts.

Common failures and fixes

SymptomEvidence to inspectCorrect owner
Character is 100 times too large or smallsource units, rest-world-scale, Unity Scale Factor and Convert UnitsFix source units in the DCC or set the importer intentionally; do not infer a factor from height.
Prop or IK target is offset after importrest-world-scale ancestry plus Unity root compensationRemove a supported compensating skinned scale with scale rest-bind, or fix the hierarchy/import policy.
Character glides or runs in placein-place, root-motion-speed, declared movement owners, three root extraction settingsAlign clip intent, Unity bake/extract choices, and controller ownership.
Loop hitches once per cycleduplicate-loop-endpoint, loop-closure, seam velocity checksCorrect the cut in the DCC or use the exact eligible endpoint transform; verify again in Unity.
Humanoid retarget differs from sourcerequired-bones, bind-pose, scale checks, Unity import messagesRepair mapping/rest pose in the DCC or Avatar configuration; AnimSmith does not certify retarget quality.

Scale and unit workflow

Unity documents one imported world unit as one metre for its physics-oriented scale convention. That does not mean every file should be multiplied until its root Transform reads one: source units, importer conversion, and inherited bone scale are separate domains. An inherited bone scale also multiplies descendant socket, attachment, IK, and collision-anchor offsets, authored animation translations, and measured root travel.

  • If every represented length is wrong, use DCC unit correction or the supported glTF/GLB scale whole-document operation before producing the Unity FBX. FBX whole-document scaling is not supported.
  • If world geometry is already correct but one skinned hierarchy carries a compensating uniform scale, use the explicit scale rest-bind design. FBX input is re-encoded to a proved GLB, so a downstream FBX requirement still needs a deliberate DCC/export step.
  • convert --bake-static-mesh-transforms is for static, unskinned placement. It is not a substitute for skinned rest/bind reparameterization.

Before: a hand socket inherits scale 0.01, so a unit-sized prop or IK offset is scaled unexpectedly. After a successful rest/bind operation: the measured world geometry and joint trajectories are preserved while the selected hierarchy is reparameterized to the declared factor. Still verify Avatar mapping, attachments, collision anchors, root motion, compression, blending, and a player build in Unity. See Scaling safely for the exact write set and proof boundary.