- Home /
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.
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.
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.
Answer by blindrenderer · Feb 04, 2012 at 08:51 PM
I actually managed to do this by extracting only rotation info from the anim clip.
Make a script called ConvertToRotationOnlyAnim.cs inside of Assets/Editor folder.
Add a menu item invoking this script.
Import your animation into Unity. (doesn't matter where it's from as long as Unity sees it as animation)
Right-click on the imported animation asset and select the menu item we just added at step #2.
In the Script, copy over only the curves which have "m_LocalRotation" as propertyName field.
Now set the new _rot animation clip to your game object's animation component.
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");
}
}
Thanks for the detailed answer and code! I'm sure this will come in handy for a lot of people.
Heh, I hope so.. it was my 3rd day playing with Unity :)
I've come across this issue as well with various proportioned characters sharing a similar rig. I am using Blender for the rigging and animation, and am hoping to share animations within Unity.
I've used the script above to variating success, but I've found the results are still not comparable to the ones I've found with simple linking of animation actions within Blender. The bones still revert to initial character's proportions when applying the animation data, even the _rot animations have problems with reverting the rig.
The only difference between the rigs is the positioning of the head/tail of the bones to accomodate proportional changes, and not the scaling or positioning of the bones.
Is there a solution to this problem, or possibly a helpful pointer in the direction that I could go in? Could there be something that I'm doing wrong with the rigging of the characters?
Thanks in advance!