Sharing animations between models

I’ve made a basic animation set for my character, and now I want to also use those animations for some of the other characters in my game. Transferring the animations within 3ds max and then exporting each different animation for each different character could be done, but that would be time consuming and use a lot of unnecessary data.

I made the new character have the same bone names but the bones have different proportions to match the model, and I had the expectation that I would be able to reuse the the animations I’ve already made. So, I’ve tried adding my animations to this other character through Animations in the inspector, and it does work, but it looks like bone locations are being transferred to where they would be in the model it was originally created for. Here is an example of what I get, next to how it should be.

alt text

What I want is for the animation clip to only use the bone rotation data, and use the bone position data of the skinned mesh that it’s attached it. There must be a way to do this, as sharing animations between different models is very common in game engines like Source and Unreal.

I actually managed to do this by extracting only rotation info from the anim clip.

  1. Make a script called ConvertToRotationOnlyAnim.cs inside of Assets/Editor folder.
  2. Add a menu item invoking this script.
  3. Import your animation into Unity. (doesn’t matter where it’s from as long as Unity sees it as animation)
  4. Right-click on the imported animation asset and select the menu item we just added at step #2.
  5. In the Script, copy over only the curves which have “m_LocalRotation” as propertyName field.
  6. Now set the new _rot animation clip to your game object’s animation component.
  7. Hit play and enjoy… :slight_smile:

This is the full source code, I posted with some more explanation on my blog.

using UnityEditor;
using UnityEngine;

using System.IO;

public class ConvertToRotationOnlyAnim
{
    [MenuItem("Assets/Convert To Rotation Animation")]
    static void ConvertToRotationAnimation()
    {
        // Get Selected Animation Clip
        AnimationClip sourceClip = Selection.activeObject as AnimationClip;
        if (sourceClip == null)
        {
            Debug.Log("Please select an animation clip");
            return;
        }

        // Rotation only anim clip will have "_rot" post fix at the end
        const string destPostfix = "_rot";

        string sourcePath = AssetDatabase.GetAssetPath(sourceClip);
        string destPath = Path.Combine(Path.GetDirectoryName(sourcePath), sourceClip.name) + destPostfix + ".anim";

        // first try to open existing clip to avoid losing reference to this animation from other meshes that are already using it.
        AnimationClip destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;
        if (destClip == null)
        {
            // existing clip not found.  Let's create a new one
            Debug.Log("creating a new rotation only animation at " + destPath);
            
            destClip = new AnimationClip();
            destClip.name = sourceClip.name + destPostfix;

            AssetDatabase.CreateAsset(destClip, destPath);
            AssetDatabase.Refresh();

            // and let's load it back, just to make sure it's created?
            destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;
        }

        if (destClip == null)
        {
            Debug.Log("cannot create/open the rotation only anim at " + destPath);
            return;
        }

        // clear all the existing curves from destination.
        destClip.ClearCurves();

        // Now copy only rotation curves
        AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(sourceClip, true);
        foreach (AnimationClipCurveData curveData in curveDatas)
        {
            if (curveData.propertyName.Contains("m_LocalRotation"))
            {
                AnimationUtility.SetEditorCurve(
                    destClip,
                    curveData.path,
                    curveData.type,
                    curveData.propertyName,
                    curveData.curve
                );
            }
        }

        Debug.Log("Hooray! Coverting to rotation-only anim to " + destClip.name + " is done");
    }
}

How would this work with Blender?