RECORDING PHYSICS FOR SECONDARY MOTION
Using Unity Version 2019.4
Secondary motion is one of the most difficult areas of keyframe animation. Done correctly, it will elevate any animation because the movement can tell us so much about a scene that we don’t know – the direction and strength of the wind, the intensity or elegance of a character’s physicality. But done even slightly wrong, it’s a prime contender to destroy immersion.
Why this works: If you recall any high school science, “physics” refers to the branch of science related to energy and matter, including movement. It encompasses the study of how an object moves or responds in relation to acceleration, collision, gravity, friction, and other forces. In Unity, the physics engine works to apply those forces in a natural way.
With cloth and hair, air resistance and mass play such a vital role that their secondary motion will behave differently from other parts of the character – like legs and arms. Subsequently, physics assets are a fantastic solution to apply cloth and hair movement in conjunction with body motion. These assets normally work along joints to procedurally implement physical forces along the chain. In seconds, your character (or any model, really) can go from flat and unnatural to lifelike and vibrant.
Why it might not work: There are drawbacks to using physics assets. For instance, it can be expensive from an efficiency standpoint since they are constantly calculating forces and collisions. Additionally, they require colliders to be set up to avoid clipping, which can go wayward if the mesh clips past the collider. And finally, because the movements are procedural, they can be unpredictable.
It’s really up to you. For the most part, and in many situations, the physics engine works exceptionally well.
But there is a way to have the best of both worlds.
In version 2017.1, Unity began experimenting with the GameObjectRecorder feature, which allows you to record data from a GameObject and its children. One of it’s drawbacks is that it does not capture humanoid data but it does capture bone transforms that aren’t part of a humanoid rig like wings, hair, clothing extensions, etc. In that sense, it’s actually ideal to record secondary motion. By using the test scripting from the initial feature feedback thread, I was able to do exactly what I needed with some minor adjustments.
What you will need:
A physics asset that works with transforms. To my knowledge, this doesn’t work on vertices, so I can’t say that assets like Obi Cloth will work. Regardless, I haven’t tested it that way, so if you do, let me know what happens. I use Dynamic Bone.
A character or object that has it’s cloth/hair rigged and weighted properly. I’ll be using my Scarlett Riley character
An animation that you want to add secondary motion to. I grabbed a roundhouse kick animation from Mixamo
Let's take a look at the animation without any physics or secondary motion. It feels pretty flat.
First, this is the original code from the forum thread:
There are only two changes needed. When the feature was moved from the Unity.Experimental.Animation API to the Unity.Animation API, they consolidated the GameRecorderObject to take a gameObject constructor. So you simply need to change the Start function from this:
Remember to also change the API at the top of the script from Unity.Experimental.Animation to Unity.Animation.
The next, and most important part of the setup, is to make sure your physics asset is set to execute ahead of the recording script. If you don’t do this, none of the physics keyframes will be captured. In my case, I set Dynamic Bone to something like -500.
Add the physics asset to your character and run the animation in play mode. Tweak the parameters until you like the results of the movement. Once you’re happy with how it all looks, copy the values, exit play mode, and paste the values into the asset in edit mode.
Now add the HierarchyRecorder script to you character or object. Before you get started, you need to create an empty animation clip to capture the data from the recorder. I put this on my animator, but I don’t think you have to. Drag this clip to the appropriate field in the HierarchyRecorder inspector.
Recording is controlled by the “Record” bool. It begins capturing when it’s true and creates the clip data when it’s false. That means that if you exit playmode without toggling the bool, the data will not be recorded. You must start and end the recording manually, while in play mode.
There are three paths you can take from here:
Set the “record” bool to true and run an unlooped clip to clearly demarcate the start and end. Click the bool to false once the character stops moving.
Set the clip to loop and choose at what point you want to start/end the recording.
Set up a helper script to capture the exact start and end of the clip.
I went for option three for a couple of reasons. First, I find that some physics assets (Dynamic Bone included) can “jump” slightly upon entering playmode, so Option 1 isn’t my preference as I don’t want to begin capturing data until the physics have smoothed out. Second, by definition, it’s difficult to eyeball the start and end of looped clips and third, I don’t want to have a giant animation clip to deal with. I want to just be able to copy/paste the recorded data to the final animation clip. That eliminates the second option.
With that in mind, here’s my helper script. This code will do three things: 1) It will display the total normalized time, in addition to the normalized time in the current loop, 2) It will start the recording after the first loop (so the physics have evened out), and 3) It will end the recording when the second loop completes.
With our scripts ready to go, we can enter playmode, which will activate our helper and recorder scripts. Below, you can see the Record bool turn true after one loop has completed, and false after a second loop.
Once they’ve completed, exit playmode and open the animation clip that was populated.
Highlight the keyframes you want to copy to the original clip. Even though you can’t edit Humanoid rig elements, you can play with the new keyframes to your hearts’ content. This is where you can adjust and account for any clipping or odd distortions, should they exist.
Now all you need to do is remove the physics asset, hierarchy recorder and helper script from your character and enter playmode again. You should see your animation run with the new secondary motion!
Here's the completed animation with just the keyframes and Dynamic Bone removed. As you can see the ends of the hair follow the motion naturally, with no jarring jumps and or risk of clipping!
Used in this article: