What binds animator bones transforms to animation itself?

If you have character model with animator, it also has big transform hierachy with bones. You can put Head bone away, transform will stop syncing, you can put it back, it will move again with animation, but there are no components and stuff like that. How this works?
Is there a way to say “this transform should be considered a head bone now and sync with it?”

AnimationClips find the thing they need by the names in the hierarchy, like a file path.

The linking between bones and the actual skinned mesh is pretty simple. The mesh contains “boneweights”. Those give each vertex of the mesh one or multiple bone references based on an index. Those references have an associated “weight” how much each of those bones influence the vertex. So a vertex may be influenced by bone number 3 (20%), 5 (30%) and 22 (50%). Besides the boneweights there are also “bindposes” defined which simply encode the initial orientation of each bone in order to figure out the relative change that a bone has on the vertices.

The bones themselfs are of course not part of the Mesh. Those are specified in the SkinnedMeshRenderer component. This component has a “bones” Transform array. The bones in that array don’t have some general ordering but are created / imported along with the mesh. So the transforms that represent the bones actually control the skinning of the mesh.

Animations simply control the transforms and have nothing to do with the actual mesh. In other words an animation does not care or even know about the mesh, it only controls the bone transforms. Animations have individual animation curves for any kind of properties of components. So skeletal animations usually just control the transforms position / rotation, however an animation could also control a public variable in one of your own components. The animation curves are “linked” to the specific gameobject through a string “path” binding. This path not only defines which relative gameobject to control, but also define the name of the property which should be controlled.

Besides skeletal animations Unity now also supports morphtarget animations which are called blendshapes which do not use any bones. Instead a morph target is a complete new set of vertices. The idea here is that the old vertices are simply “morphed” / lerped to the new ones. This is useful for complex animations that are hard or impossible to represent with bones. All the data for Morphtargets / Blendshapes are defined in the Mesh itself.

To sum up:

AnimationClips simply animate properties of components. For skeletal animations that usually means the localRotation / localPosition of Transform components of the bone gameobjects.

The actual skinning of a skinned mesh is done through the crossplay between the SkinnedMeshRenderer and the skinning information inside the Mesh. Note that the bones array is not visible through the inspector.

Note that besides generic skeletal bone animations, Unity also supports humanoid skeletons where generic humanoid animations can be used on. The special humanoid type knows a fixed set of bones which can be assigned in the animation avatar. Check your model importer and view the “rig” and “animation” tab.

2 Likes

Does it works by transform HashCode? GameObject name don’t affect that.

This page has some quick sample code you can fiddle with to understand the bindings:

The code works perfectly and shows you absolutely nothing. Here’s why:

They wound their triangles to face AWAY from the camera.

To fix the broken example code at the page above, replace the triangle ordering line:

mesh.triangles = new int[] {0, 2, 1, 1, 2, 3};

Then you’ll be able to see the animated mesh looking at it +Z (default camera).

Nearly six years ago (December 2015) I pointed this error out to Unity and they still haven’t fixed it.

1 Like

Well, all of that is overcomplicated for me.
It’s so easy to use bones provided by model, it’s so easy to call Animator.GetBoneTransform, but simply adding new transform to act like bone… Why there is no SetBoneTransform(BoneType.Head, transform) then? I’m too stupid for other approach. My brain disables when I see matrices, meshes, indexes etc. I tried to somehow implement it, but it doesn’t work, I feel like 1 day in Unity, I don’t even know where to start. Anyway, thanks all. Guess I’ll choose more common approach, and return to all of that later.