Lesson 7 : advanced hand rig
In this course, we will learn how to create an advanced hand rigging system so that it can be easily animated.
We will use all sorts of Maya features, whether through simple matrix constraints or set driven keys. We will learn how to place the joints, animate them, and, of course, we will discuss all the relevant theory that we will use for this.
Table of Contents
1. How to place bones and Controllers
2. Making predefined animations
3. How to connect hands to arms
4. Skin hand
5. Sources
1. How to place bones and Controllers
The hand may seem like a relatively simple part of the body to rig, but in reality, it is not necessarily the case. The main problem we will encounter when rigging hands will be preserving volume, as there are many rotations that will occur on each phalanx and each metacarpal of the hand, which can subsequently create a lot of destructive deformation or make it quite challenging to create an effective skin.
​
So, the first step that will be very important is to place the joints in the right places as precisely as possible. This will be crucial for achieving good deformations.
In the first course I made on how to create a body rig, I explained how to place the fingers on the phalanges using the 2/3 method, which allows you to place your joints at 2/3 of the diameter of your articulation.
The first important thing for placing the first phalanx of each finger is to align them along the curve of the phalanges. On our hand, if we look at reality, there is a curve created at the level of the first phalanges, which varies in size depending on the morphology of individuals.
​
This line is very important to reproduce when placing the joints to achieve a nice deformation when we close the hand. This will allow us to have a good shape when the fist is clenched.
It is therefore necessary to identify this line in your model, which will vary in height depending on your character's design, and then place the joints of each phalanx according to this guideline.
There will also be a curve in the height of the hand. This curve is caused by the metacarpals of the hand, which allows you to move your phalanges more easily to grasp objects.
Once the phalanges of your fingers are placed, you will need to do the same for the thumb. The thumb attaches to the metacarpal of the thumb, which is itself connected to the wrist inside the hand. The advantage here is that the phalanges and the metacarpal are continuously aligned, which makes the placement process quite simple and very similar to what we have seen before. The only truly important position will be the metacarpal of the thumb, which is situated slightly higher than the bump on your thumb.
At this point, you have all your phalanges and the metacarpal of your thumb in place. Now, you need to create the metacarpals for your fingers. To do this, we will follow the same process as before, which is to analyze real images to determine where to place the metacarpal joints correctly.
​
​
​
​
Generally, the metacarpals are fairly aligned; they all follow the same line of force with only minor rotations between them. Additionally, the metacarpal and the middle phalanges are always aligned with the bones of the arm, which will provide a reference for placing them more easily.
First, you need to place 4 joints along this line, with a slight curve because your hand is not flat but has a subtle volume curve. These 4 joints will need to have very precise rotations to ensure that the rotation of the metacarpals occurs correctly and that there are nice and good deformations.
​
To do this, after placing the 4 joints as shown.
You will need to apply a temporary aim constraint on your metacarpals towards the first phalanx to ensure that the rotation aligns precisely with the finger's axis, to avoid unwanted deformations.
For example, for the index metacarpal, the X axis (the rotation axis of your metacarpal) should be aligned with the direction of the first phalanx of the index finger. Once this alignment is done, you can remove the constraint; it is only used to correctly position your joints.
After setting up all the aim constraints, you can rotate the joints along the X axis to ensure they align and create a smooth curve, making it visually appealing for when we later place the controllers. Finally, we will parent each metacarpal from right to left so that our hierarchy looks like this:
We organize the metacarpals in this way to achieve more precise and smoother control during animation. In reality, the metacarpals don’t move much individually, but as they move one after another, it creates slight rotations that add up, resulting in a larger overall rotation. You can observe this on your hand: the central metacarpal doesn’t move much, but the one at the end moves significantly.
You only have one step left: place the phalanges of your fingers within the corresponding metacarpals. This will give you a hierarchy that looks like this:
Then, all that remains is to create a joint for the wrist and place it in the correct position. (If you already have a joint that serves as the wrist, you can reuse it, as I have done in this case.)
Once all the joints are placed, we can start placing the controllers. To do this, we will follow the same process as in the course "How rig a body character" First, we will create a controller for each phalanx and metacarpal, and then we will match-transform them onto the joints.
We need to ensure that we replicate the exact same hierarchy as for our joints, which will give us this setup:
To do this, there is nothing new; we will use the same constraints and connections as we did in the first course. We will use the "decompose matrix" node and apply each controller's World matrix.
I will repeat verbatim what I said in the first course:
from here, to enable the controllers to move the fingers, we have two options. The first is to use a parenting system similar to what we did with the spine, where we directly place the joints under the controller. This method is efficient in terms of rigging but may not be ideal for clarity when it comes to skinning or other tasks.
Alternatively, the second technique is more complex but offers better control and optimization for the rig. We'll use matrix constraints in Maya, specifically a parent constraint, which will allow us to maintain a clear hierarchy in the outliner while achieving efficient rig performance.
​
To implement our matrix constraint system, we'll follow a similar process to the pairBlend method, but without using pairBlend itself. Here's how we'll do it:
-
Decompose Matrix: Use a Decompose Matrix node to extract the world position of the controller. Connect the rotation and translation outputs to the corresponding finger joint.
-
World Inverse Matrix: Retrieve the world inverse matrix of the parent of the finger joint we're working on. This inverse matrix ensures that the finger joint follows the controller accurately.
​
Ensure that the joint orient of all finger joints is zeroed out to ensure perfect finger positioning. This approach using matrix constraints will provide us with precise control over finger movements while maintaining a structured hierarchy in the outliner, making it easier to manage and skin later on.
(Make sure to zero out the joint orient for all joints to ensure perfect finger positioning.)
Once you've done this for one finger, repeat the process for all the other fingers, phalanges, and metacarpals, making sure to connect the offset for each joint properly to avoid misalignment of your fingers.
​​​​
From this point on, you will be able to move your fingers without issues, allowing you to animate and modify them as needed. A simple trick to check if your fingers are properly positioned and oriented is to close all the fingers (excluding the thumb). They should all align correctly to form a good fist. If they don’t, it’s not a big issue. You can move and rearrange your joints by adjusting the "root_..." groups of your controllers, and the joints will follow accordingly.
Now, we will perform a series of small actions that will enhance control and create automations, making hand animation much easier and resulting in smoother and more pleasant animations.
2. Making predefined animations
We have just finished setting up the hand; now we will move on to a stage that is more artistic and less technical. This will depend on your preferences, the style of animation you want to achieve with the rig, and your personal taste.
In this part, we will explore how to create predefined animations triggered by attributes or the translation of an external controller, which will position your fingers and phalanges in specific poses to give you better control.
Whether it's animations for closing the fingers, splitting them, holding an object, or creating overlaps with your fingers, we will cover all of this from now on.
​
​
To start, the first thing we need to do is create an additional group for each finger controller. This group should be placed between the root and the finger controller. We can prefix this group with "DriveKey_". This group will allow us to create all our "set driven keys" on this group, thus avoiding interference with the root and giving animators control over the basic controllers.
Next, we will create a controller above the hand that will allow us to manage all the animations for the hand and serve as the primary controller for the hand.
With this controller, we can create attributes to drive the animations or use the controller's translation to drive the animations.
​
In our demo, we will use the controller's translations and rotations for global movements and attributes to control individual parts, such as animating each finger separately.
​
We will add an attribute to the controller for each finger to control bending and stretching, using a float attribute ranging from -5 to 10. Additionally, we will create an attribute for spreading the fingers, with a float range from -10 to 10. We will also add an attribute to rotate the metacarpals of the hand, using a float attribute ranging from 0 to 10. For now, this will be sufficient; we can add more animations later or integrate them directly into the controller's translations.
for fingers
for split
for Metacarpals
Once all the attributes are created, we can start setting up the driven keys. We'll begin with the pinky finger. First, select the three "driveKey_...." groups for the pinky finger. Once selected, go to the Channel Box, choose any attribute, go to Edit, and select Set Driven Key.
The advantage of selecting the groups initially is that it will automatically use this selection as the driven objects. You will only need to reference the driver before you start setting up the driven keys.
Once we have set up the drivers and driven objects, we can start setting our first keyframe to define the zero state. When the "pinky" attribute on the controller is at zero, all the "driveKey_...." groups should also be at zero. If everything is at zero, select only the X axis for all the groups in the driven list to set a keyframe only for this axis.
Once we have our initial state, we can rotate the groups to bend the finger. It's crucial to have precise rotation (e.g., 20 degrees) for closing the finger so that we can reuse this value for other fingers, ensuring uniform finger closure. (Of course, before setting the keyframe, make sure the "pinky" attribute is set to 10 to create the transition.)
Then, return to the initial state (zero), and bend the finger in the opposite direction to create the effect of overextension. Avoid overdoing it, as it can quickly look unnatural. Follow the same process, maintaining precise rotation values for each finger, and remember to set the "pinky" attribute to -5, the minimum possible value.
Once the pinky is done, you need to repeat the same process for the other four fingers, including the thumb. After this, you should understand the mechanism and operation of this method, which will allow you to trigger and perform various actions using driven keys.
(Note: For the thumb, only use the last two phalanges, and it will have its own rotation degrees.)
Now, let's focus on the "split" attribute. This attribute will allow us to create an animation that spreads the fingers apart or brings them closer together.
To do this, we will use the same principle and tools. This time, select all the "drivenKey_..." groups of the first phalanges of each finger and use them as driven objects, with the "split" attribute of the controller as the driver. Note that for the thumb, you should use the "drivenKey_..." group of the metacarpal, not the first phalanx.
​
We will follow the same methodology: first, ensure all values are at zero in the drivers. Select the Y rotation axis, as we will perform the split on this axis to separate or bring the fingers closer. Create the initial keyframe at zero. Then, set the "split" attribute of the controller to 10, position the "drivenKey_..." groups accordingly, and set the keyframe in the split position.
Do the same for the value -10, but this time, adjust the fingers to be close together.
For the final attribute, we will use the metacarpals of the fingers to achieve the rotation needed to touch the thumb to the pinky. This rotation is performed by the metacarpals and is essential for allowing the hand to grasp objects effectively.
​
To do this, follow the same method as before: select all the "drivenKey_..." groups of the metacarpals (except for the thumb and index). Use the Set Driven Key tool in the same manner as previously. For this setup, use the metacarpal attribute of your controller as the driver and the X axis of the "drivenKey_..." groups of the metacarpals as the rotation axis. Simply input the desired values to create the rotation. This follows the same principle as what we did earlier.
With the set driven keys we’ve created, we can establish predefined animations that can be toggled on or off, allowing the hand to assume specific positions and making the process more convenient. For example, we will use the translation of the controller to adjust the hand's closure.
​
We will set up connections so that when we move the controller positively along the X axis, the hand closes, and when we move it negatively, the hand opens further.
​
To achieve this, we'll perform some simple connections in the Node Editor. First, retrieve all the animation curves (animCurves) created by the set driven keys for the phalanges of each finger from the Node Editor.
As shown in the image, the animCurveUA nodes are each connected to an attribute of the controller, allowing us to control the output value of the animCurveUA node. This setup functions similarly to a remap node with multiple precise values.
To make our connections, first, we will retrieve the X translation of the c_controller_hand_L and add it to each animCurveUA. Essentially, we will use an addDoubleLinear node to combine the values from each attribute with the X translation of the controller. This setup enables the hand to be manipulated either through attributes or directly via the controller, providing significant flexibility in the rig and allowing animators to control the hand as they prefer.
With this technique, using set driven keys (set driven keys) ensures that we have rotation limits, avoiding issues like excessive penetration or unnatural visual distortions, which helps produce more realistic animations.
​
However, I'd like to add an additional mode that allows us to adjust the distance the controller travels for finger closure. In our example, since we are directly connecting the translation to the animCurveUA (via an addDoubleLinear node), this means we need to move the controller along the X axis to a maximum value of 10 for the hand to close completely. This might seem impractical because moving the controller to an X translation of 10 feels quite far and involves a significant distance.
​
To address this, we use a remapValue node to adjust the values to a more manageable distance. For instance, with this remapValue, we can set it so that when the controller's translation is 3, the output will be 10, effectively converting 10 Maya units into just 3 units.​
We will use two remapValue nodes: one for positive values and another for negative values. This setup will allow control over both positive and negative ranges and provide precise control over the distances. Since we are using different remapValue nodes, we need a final addDoubleLinear node to combine these two remapValue nodes into a single output.
The advantage of using the remapValue node is that it allows us to adjust the controller's range so that the hand can be fully opened or closed with a shorter, more efficient range. For example, we can adjust the range from -5 to 20 to -3 to 3. This provides a more compact and effective range, but if this does not suit your needs, you can always adjust the maximum input values of the remapValue nodes to choose the distance you prefer.
​
We could have used a set driven key to mix the finger closures between attributes and translation. However, the issue with applying multiple set driven keys to a single attribute is that they accumulate. This means if we set the "Pinky" attribute to 5, 8, or 10, and then adjust the X translation of the controller, the Pinky could end up rotating excessively, resulting in multiple rotations and creating an undesirable effect. Therefore, we use addDoubleLinear nodes with remapValue nodes to ensure that the maximum rotations are bounded and cannot exceed specified limits.
Improper usage, only set driven keys, no bone limit constraints or potential overrides.
Proper usage by using remapValue with addDoubleLinear, constrained movement, more realistic and precise motion.
Now we are going to create an animation that allows us to bend and straighten the fingers from left to right.
What I mean is that the further the controller is to the left, the more the fingers on the left side will bend, meaning that the index finger will be the most bent and the pinky will be the least bent. Conversely, as you move the controller to the right, the opposite will occur: the rightmost fingers (the pinky) will bend more, while the index finger will bend the least. Here’s an example in a GIF to make it visually clearer.
To achieve this, we'll use the same principle we applied for opening and closing the hand. We'll use remapValue nodes to adjust the output values for each finger to create the effect of bending more or less.
For instance, the first remapValue (e.g., for the index finger) will have a maximum output value of 10 (with 10 being the maximum of the animeCurveUA). The last remapValue (e.g., for the pinky) will have a maximum output value of 2.5. This ensures that the index finger bends more and the pinky bends less when the controller is moved in one direction, and vice versa in the opposite direction.
Here are the steps:
-
Add Nodes: For each phalanx, add an addDoubleLinear node before the animeCurveUA node.
-
Connect remapValue Nodes: Add two remapValue nodes per finger. Connect these two remapValue nodes to another addDoubleLinear node, which is then connected to the first addDoubleLinear node.
-
Setup Connections: This setup will allow you to control the bending of each finger independently in terms of rotation.
Once we have set this up, we need to connect all the remapValue nodes we created to the translateZ attribute. For all positive remapValue nodes, set the same maximum input value for each, which will be the maximum translation you want in your scene. In our example, we'll use a value of 3, as we did for the X-axis.
​
Next, for the maximum output value, you should use a different value for each finger, increasing incrementally. For the fingers (index, middle, ring, pinky), take the maximum value that the fingers can reach when the hand is fully closed (which is 10, the maximum value of animeCurveUA) and divide by the number of fingers, which is currently 4. This gives us a result of 10 / 4 = 2.5.
We will use this 2.5 value and multiply it according to the finger number to achieve increasing rotation values. For example, if the controller moves positively along the Z-axis with a translation of 3, we want the pinky to be the least closed and the index to be the most closed. Here’s how to set the remapValue output maximum values:
-
Pinky: Set the output maximum to 2.5
-
Ring: Set the output maximum to 2.5 * 2 = 5.0
-
Middle: Set the output maximum to 2.5 * 3 = 7.5
-
Index: Set the output maximum to 2.5 * 4 = 10.0
​
To summarize the calculations:
-
Pinky = 2.5 * 1 = 2.5
-
Ring = 2.5 * 2 = 5.0
-
Middle = 2.5 * 3 = 7.5
-
Index = 2.5 * 4 = 10.0
For the negative remaps, you will simply reverse the calculations. The output maximum for the index should be set to 2.5, and the output maximum for the pinky should be set to 10. Here's how the calculations will look:
pinky : 2.5 * 4 = 10.0
ring : 2.5 * 3 = 7.5
middle : 2.5 * 2 = 5.0
index : 2.5 * 1 = 2.5
​
For the maximum input value, it will be the opposite of what we used for the positive values. In this case, we will use -3.
This method might seem a bit unconventional, but it allows you to create a lot of variations in hand movements by adjusting just this control. It adds significant effects and realism to finger and hand movements, which can save you a lot of time when animating hands.
It will enable you to optimize and create default animations with unprecedented simplicity.​
The advantage of this approach is that it allows you to add a great deal of detail to finger movements. Thanks to the remaps and various Maya nodes, you can create all sorts of predefined animations, saving you a lot of time. In this course, we’ll stop here, but you now have all the tools you need to create your own custom animations, whether it's just for bending the tips of the fingers or other actions. You can use the same method, whether with attributes, controller translations, or other techniques.
3. How to connect hands to arms
To connect the hand to the arm, we'll use the same method as shown in the course "How rig a body character" Specifically, we'll employ matrix constraints with a pair blend.
-
Create an Empty Group: First, create an empty group and match its transformation to the wrist joint. This group will serve as a reference for the joint "Wrist_L"
-
Set Up Matrix Constraint: Use this group to set up a matrix constraint with the "Wrist_L" joint. This will ensure that any movement applied to this group will affect the wrist joint accordingly.
-
Parent the Two: Parent the group to the "Wrist_L" joint via the matrix constraint. This setup will allow you to move the entire hand and its controllers, and consequently, move all associated joints smoothly.
-
Ensure Proper Movement: Confirm that when you move the controllers and the group, the wrist and the entire hand rig behave correctly, allowing for smooth transitions and movements.
This method ensures that the hand is properly integrated with the arm, maintaining proper joint alignment and movement synchronization.
Here’s how you can complete the rigging by integrating the hand control with the wrist control using a pair blend:
1.Create a Hand Control Group:
-
Create an empty group named Hand_Control_L.
-
Match its transformation to the wrist joint to ensure that it aligns properly with the wrist.
​
2.Add Controllers to the Group:
-
Place all the hand controllers (including those for the fingers) into this Hand_Control_L group. This will allow you to control the entire hand's movements through this group.
​
3.Create a Pair Blend Constraint:
-
Set up a pair blend constraint between the FK wrist controller (c_Wrist_L_FK) and the IK wrist controller (c_Wrist_L_IK).
-
The pair blend constraint will enable smooth transitions between FK and IK modes for the wrist.
​
4.Connect the Hand Control Group:
-
Apply the pair blend constraint to the Hand_Control_L group, linking it with the FK and IK wrist controllers. This will allow you to blend between FK and IK control while manipulating the hand.
​
By following these steps, you’ll ensure that the hand control is fully integrated with the wrist and can transition smoothly between FK and IK modes, providing flexible and intuitive control over the hand rig.
Be sure to change the rotation interpolation in the pair blend to quaternion mode; this will help prevent your hand or objects from spinning multiple times on themselves during interpolation.
Once you have created the pairBlend and made the connections as shown in the example above, you need to connect the weight of the pairBlend to the attribute of your IK/FK switch so that your hand can follow the position of both IK and FK.
Be careful with the connections in the pairBlend. The IK controller should be connected to input rotations and translations number 1, and the FK controllers should be connected to input rotations and translations number 2. This is important because if reversed, you will have a mismatch between the hand and the rest of your arm.
As you may have noticed, the controller 'c_twist_Wrist_L' does not follow the wrist because, as you remember from the course on creating ribbon systems, we adapted this system for an arm by using the position of the hand to create a constraint point on it. This allowed us to keep the arm always oriented correctly.
To fix this, it's quite simple. Just create a proper constraint on the group 'cstr_twist_Wrist_L' using 'Hand_Control_L' as the reference.
Once you reach this stage, if you have created a ribbon system on your arm like in the example, you will need a constraint on the locator used as your target, 'loc_target_Wrist_arm_L'. This locator is used to decompose the Z-axis to create the forearm rotation effect.
​
Simply reset the locator to zero to set it to its original position, and create a parent constraint on the locator 'loc_target_Wrist_arm_L', using 'Hand_Control_L' as the reference. Once this is done, the forearm rotation will be restored to its correct state.
Congratulations, you have completed this step. If you followed everything correctly, the hand will properly follow your arm in both IK and FK modes, and the forearm rotation will work perfectly as well.
4. Skin hand
The final step is to select the appropriate joints to skin the hand. This will be straightforward. Select all the joints of the hand, everything we have created since the beginning of the course, then select our model in this case, our body and add the skin influences by going to Skin > Edit Influences > Add Influence.
​
We will skin as usual, starting with one joint influence per vertex to achieve raw deformations, and then smooth them to get better deformation. Additionally, for the hand, it is recommended to have a maximum of 5 influences on the skin to allow for more precise control over the deformation later on.
If you enable the weight locking parameter, make sure to go to Paint Skin Weights and select all the locked joints to unlock them.
Next, once this step is complete, you will need to paint each phalanx with its corresponding joint. Paint the entire hand with the "Wrist_L" joint. Then, use the Smooth tool to create better transitions between the different parts. Finally, gradually add influence with the metacarpal joints to create the deformation of the metacarpals. The skinning process remains quite basic and not very complex.
version No Smooth
version Smooth
skin Metacarpals​
Congratulations, you have completed this course! The advantage of rigging a hand using the set driven key and remap methods is that you can control each finger, each phalanx, and every part of your hand as desired. This allows you to create any type of preset animation that the animator can use to achieve the most accurate animation possible.
Of course, you can always add more complexity and additional controls to the hand rig. For example, you could implement an IK system for each finger if you want the character to be able to place each fingertip on a surface and move the hand while keeping the fingers in contact with the surface, similar to Spider-Man.
I hope this lesson has served you well !