x


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.

more ▼

asked Dec 03 at 01:42 AM

jRocket\'s gravatar image

John Ross Porter
16 1 1 3

Engines like Source and Unreal are somewhat higher-level than Unity- it's possible to do this, but not through any facilities provided you by default. Try writing a script which translates animation data between skeletons.

Dec 03 at 02:53 AM syclamoth
(comments are locked)
10|3000 characters needed characters left
 moderation talk

1 answer:

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... :)

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");
    }
}
more ▼

answered Feb 04 at 08:51 PM

blindrenderer\'s gravatar image

blindrenderer
31 1

Thanks for the detailed answer and code! I'm sure this will come in handy for a lot of people.

Feb 06 at 05:21 AM jRocket

Heh, I hope so.. it was my 3rd day playing with Unity :)

Feb 06 at 05:27 AM blindrenderer
(comments are locked)
10|3000 characters needed characters left
 moderation talk
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x2070
x625

Asked: Dec 03 at 01:42 AM

Seen: 542 times

Last Updated: Dec 02 at 09:20 PM

powered by Qato - Enterprise Q&A