Object Interaction
Eventually in animation you will encounter this tricky but common scenario: An object will need to be held by a character and then transition to being animated on its own - and vice versa! For example, a character holding a ball throws it up in the air and catches it again. The ball starts in the hand, detaches from it as it's animated flying through the air, and then goes back into the hand again. So how do we deal with these transitions?
To become familiar with animating a character interacting with objects you will be using an example file found on the network:
O:\unix\projects\instr\capstone3\cse459_au17_character_rigs\corruption_rig_constraints.ma
In this scene you will find the Corruption rig animated holding a ball, throwing it up in the air, then catching it. However, the ball hasn't been properly animated yet. It is time to fix this!
Be sure to work out of a copy of the file.
Using Multiple Copies
An older, brute force way of solving the interaction problem is using multiple copies of an object in each different location it needs to pass through. For example, in the scenario you will be working through there would be two balls: one in Corruption's hand and one not parented to anything. The trick here is that only one of these copies is visible at a time.
The ball in Corruption's hand would be seen first. As he throws it into the air, that ball is hidden and the unparented one is shown. Then when Corruption is about to catch the ball coming back down, the unparented ball is hidden and the one in his hand is shown again.
Though this method is assured to work, it can sometimes be difficult to keep track of all the parented hidden objects - for both animation and lighting. This also doesn't work very well with referencing. Because of this, most object interaction involves setups using constraints.
Direct Constraint
Having a character simply hold onto an object is the most basic character/object interaction. For a concrete example,
we will be looking at frames 10-30 in the example file.
A straightforward way of addressing this scenario would be to parent the ball directly to the hand control causing the ball
to follow along with it. Unfortunately in most of the Maya scenes we work with direct parenting is not possible because of referencing and concerns of
scene organization. Luckily, the Parent Constraint allows us to simulate parenting without actually changing the scene hierarchy.
-
Go to frame 10 and manually position the ball into the character's right hand.
-
Now to constrain the ball to the hand. The safest way to do this is through the joint. We don't want to constrain it to the hand control because FK/IK switching later will appear to break the constraint.
Search through the Outliner and select right_hand_bind_joint (transformation source), hold Ctrl and select the ball in the Outliner (transformation target),
then go to Constraint → Parent (Options). Make sure "Maintain offset" is checked then click Apply.
The ball's translate and rotate attributes will turn cyan in the Channel Box, indicating that they are driven by the constraint. The ball should
now follow along with the arm motion.
Indirect Constraint
Time to take this one step further. What if we wanted the ball to follow the hand as before, but we also wanted the freedom to animate the ball whilst the hand moves it?
Like rolling the ball around the palm in frames 40-80 while the hand moves around freely? This cannot be accomplished in the current setup since the constraint is driving the ball's translate and rotate,
thus preventing us from setting keyframes.
The solution is simple: Don't constrain the ball! Constrain an intermediary object, then parent the ball to said intermediary object. Before setting up this system back up to before the first constraint was created. Go to frame 10, select the ball, and go to Edit → Delete By Type → Constraints.
- As before start on frame 10. The ball should still be positioned in the character's right hand.
-
Go to Create → Locator. This will serve as the intermediary object. Name the locator "ball_intermed". For organization purposes this locator
should be parented to the same group as the ball - so under props. And so we can see it more easily in the viewport, set its scale x, y, and z to 15.
- Select right_hand_bind_joint, then ball_intermed and go to Constraint → Parent (Options). This time uncheck "Maintain offset" then click Apply.
The locator should snap to the center of hand.
- Directly parent the ball to ball_intermed. When you scrub the time slider it will act as it did before; however, you can set keyframes on the ball and animate it within the space of the hand.
- Animate the ball rolling around the palm in frames 40-80.
Switching: Constraints to Keyframes
Now to deal with the ball leaving the hand. The constraint is still needed at the beginning, but starting on frame 102 we want it disabled. There is a way to do this,
but things start to get a little tricky.
-
Let's make the assumption that when the ball needs to be animated freely, as in animated as if it's not
constrained to anything we will use the ball_intermed locator as our animation control. Now
for the issue of the constraint driving the values. How do we resolve this? In a way, Maya will do it for us.
Scrub to frame 102, select ball_intermed and hit the 's' key to set a keyframe.
-
All of the formerly cyan channels should turn green and a new attribute called "Blend Parent 1" appeared. Why does this happen?
In Maya animation is driven by connections. The constraint node feeds into the translate/rotate, hence the cyan channels.
Similarly when an object is keyframed, animation curve nodes feed into the translate/rotate resulting in the pink channels.
When you hit 's' to set a keyframe on ball_intermed Maya tries to hook animation curves into the object but sees there's an existing connection.
To resolve this Maya creates an inbetween "Pair Blend" node. This node acts as a way to switch between to the two animation connections, using the new "Blend Parent 1" attribute as a switcher. Setting this attribute to 1 will cause ball_intermed to use the constraint and setting it to 0 will cause ball_intermed to use the animation curves defined by keyframing.
- By setting the first keyframe on frame 102, you've happened to place ball_intermed at the point where the ball leaves the hand. If you scrub the timeline right now you'll see that it stays in the same spot. Since "Blend Parent 1" is set to 0 we're currently using keyframes for everything. Go to frame 101 and set "Blend Parent 1" to 1 so that in the beginning of the animation ball_intermed is using the parent constraint again.
- Anytime you're doing a switch like this it's usually good to set "buffer" keyframes on everything involved and not just the blend parent attribute. Set keyframes on the ball itself on frames 101 and 102 as well.
- Now that we have the switch in place it's time to start animating the ball using ball_intermed as an animation control. However, at this time the ball is likely not centered on its intermediate locator which would make it awkward to use as an anim.
The solution to this is to match the locator to where the ball is on frame 102. We need a simple way to copy the ball's position and rotation in space to ball_intermed. Usually we would use a constraint to do this for us, but we can't in this particular situation since we are already dealing with a complex setup of constraints and keyframe animation. Unfortunately, this is a place where Maya's default tools can't help us. There are some commands that could assist us but they are unecessarily complex and would only get us halfway there.
To circumvent this shortcoming we will use a script:
from pymel.core import *;s=ls(sl=1);
move(s[1],xform(s[0],q=1,ws=1,rp=1),rpr=1);
xform(s[1],ws=1,ro=xform(s[0],q=1,ws=1,ro=1));
What this script does is match a target object's translation and rotation to a specified source object. First select the source (the ball), then select the target (ball_intermed), then copy the above code and paste it into the box on the bottom left of the Maya interface.
If the button to the left says "MEL" click it to change it to "Python". Now hit Enter to run the script. The ball_intermed locator should now be where the ball was in space.
Since the ball is a child of ball_intermed it moved along with its parent. To get the ball back to its original position just zero out its translate and rotate.
- Animate ball_intermed flying straight up into the air starting on frame 102 and then falling back down to contact the hand again on frame 120.
Switching: Keyframes to Constraints
We now have the reverse problem from last time. The keyframed ball_intermed needs to switch from keyframe animation to using a constraint on frame 120. The system is already in place for this now, we just need to key the switch and perform some matching.
-
Set "buffer" keyframes on both the ball and ball_intermed on frames 119 and 120.
- Go to frame 120. On ball_intermed set "Blend Parent 1" to 1 to switch it back to using the constraint. Notice the that ball stays in the center of the control. However, we want it to keep its position in space before we toggled the blend attribute back to using the constraint.
We're going to use a temporary placeholder object to help us accomplish this. Change "Blend Parent 1" back to 0.
Go to Create → Locator. Name it saved_ball_position. This locator will be used to temporarily store the ball's positional information. Select the ball, then saved_ball_position, then run the simple matching script from before. You should see the locator snap to where the ball is.
With the ball's location stored, change "Blend Parent" to 1 again.
To restore the ball's position in space select saved_ball_position, then the ball, then run the matching script again. Voila! The ball should be where it used to be. You can now delete saved_ball_position.
- Put a couple of additional keyframes on the ball in frames 120-145 so it settles into the hand naturally.
The animation should be finished now, so go ahead and turn it in!.