Copy and Paste Unity Animation Curves / Extract Animation Curve From Animation

I use AnimationCurves for a lot of things ( tweens, changing colors, simulating root motion without Mecanim, faking physical interactions between adjacent pieces in a game I’m working on ) and sometimes it’s really helpful to be able to copy and paste a curve from one field to another. Unity left out this feature, so here’s a handy project that supports it.  With this custom AnimationCurve inspector, you can right click on the name of an AnimationCurve field in the inspector and select “Copy Animation Curve”

Evil Eye Glow Alpha: starts dark, glows bright, then goes dark again

Evil Eye Glow Alpha: starts dark, glows bright, then goes dark again

Then you can click on any other AnimationCurve field and paste that data using the “Paste Animation Curve” option, and the curve will be copied over for you to edit or use how you please.

Surprisingly, selecting "Paste" will paste your data

Surprisingly, selecting “Paste” will paste your data

Pasted! Who knew that Hair Loss Over Time so closely mirrored Evil Eye Glow?

Pasted! Who knew that Hair Loss Over Time so closely mirrored Evil Eye Glow?

You may have noticed that there’s a third option in the popup menu- “Extract From Animation…”  Instead of copying and pasting, this will let you take data from an Animation and copy it into your AnimationCurve. I wrote this for Max Axe because, for performance reasons on old hardware, we had to switch from Mecanim back to legacy animation and didn’t want to lose the root motion built into some characters’ animations.  So, I extracted the root motion channel from their run animations and used that to offset their positions in the world after the artists had nulled the channel back out.  To extract an animation, simply choose the top option from the popup menu:

Take Animation Curve data out of any Animation from your art team!

Take Animation Curve data out of any Animation from your art team!

This will open up a new Animation Curve window, waiting for you to select an Animation.  This can be any animation- either a standalone .Anim or an animation embedded in an .FBX.   After you’ve done that, you can select the transform and channel you’d like to extract, from a nicely hierarchical menu setup that mirrors your skeleton.

Pick the transform and the channel to extract

Pick the transform and the channel to extract

In this case I’m just grabbing the m_LocalPosition.z from the C_Global_ctrl since that has the character’s root motion translation in it ( he doesn’t move form side to side )

After that, you’ll see the data from that curve nicely displayed in the Data field, so you can make sure you selected what you thought you selected and not just some similarly named controller left in the exported art file.

Data filled in once transform and channel picked

Data filled in once transform and channel picked

Finally, press Extract and the data will get copied into your curve!

Looks like somebody runs at a constant speed.

Looks like somebody runs at a constant speed.

There you go, ready to rock with your Animation Curve Tools and your awesome new Animation Curve data.  Cheers!

 

Download ( or Improve! ) AnimationCurveTools on GitHub

原文地址:http://www.joshuaglazer.com/blog/copy-and-paste-unity-animation-curves-extract-animation-curve-from-animation/

附:

1、BetterAnimationCurveFieldDrawer.cs

using System;
using UnityEngine;
using UnityEditor;


[CustomPropertyDrawer( typeof( AnimationCurve ) )]
public class BetterAnimationCurveFieldDrawer : PropertyDrawer 
{
	[MenuItem ("CONTEXT/AnimationCurve/Extract From Animation...")]
    static void ExtractAnimationCurve( MenuCommand inCommand ) 
	{
		if( _PopupTargetAnimationCurveProperty != null )
		{
			AnimationCurveExtractor aceWindow = AnimationCurveExtractor.GetWindow( typeof( AnimationCurveExtractor ) ) as AnimationCurveExtractor;
			aceWindow.Init( _PopupTargetAnimationCurveProperty );
		}
    }
	
	[MenuItem ("CONTEXT/AnimationCurve/Copy Animation Curve")]
    static void CopyAnimationCurve( MenuCommand inCommand ) 
	{
		if( _PopupTargetAnimationCurveProperty != null )
		{
			_ClipBoardAnimationCurve = AnimationCurveCopier.CreateCopy( _PopupTargetAnimationCurveProperty.animationCurveValue );
		}
    }
	
	[MenuItem ("CONTEXT/AnimationCurve/Paste Animation Curve")]
    static void PasteAnimationCurve( MenuCommand inCommand ) 
	{
		if( _PopupTargetAnimationCurveProperty != null )
		{
			_PopupTargetAnimationCurveProperty.serializedObject.Update();
			_PopupTargetAnimationCurveProperty.animationCurveValue = AnimationCurveCopier.CreateCopy( _ClipBoardAnimationCurve );
			_PopupTargetAnimationCurveProperty.serializedObject.ApplyModifiedProperties();
		}
    }
	
	
	
    // Draw the property inside the given rect
   	public override void OnGUI ( Rect inRect, SerializedProperty inProperty, GUIContent inLabel ) 
	{

		var evt = Event.current;
		if( evt.type == EventType.ContextClick ) 
		{
        	var mousePos = evt.mousePosition;
			if ( inRect.Contains( mousePos ) )
			{
				_PopupTargetAnimationCurveProperty = inProperty.Copy();
				inProperty.serializedObject.Update();
				EditorUtility.DisplayPopupMenu( new Rect( mousePos.x,mousePos.y, 0, 0 ), "CONTEXT/AnimationCurve/", null );
			}
		}
		else
		{
			inLabel = EditorGUI.BeginProperty( inRect, inLabel, inProperty );
			EditorGUI.BeginChangeCheck ();
			AnimationCurve newCurve = EditorGUI.CurveField( inRect, inLabel, inProperty.animationCurveValue );
			
			if( EditorGUI.EndChangeCheck() )
			{
				inProperty.animationCurveValue = newCurve;
			}
			
			EditorGUI.EndProperty ();
			
			
		}
		
        
        
    }
	
	private static AnimationCurve _ClipBoardAnimationCurve = new AnimationCurve();

	//meun command context isn't working, so we'll just stash it here...	
	private static SerializedProperty _PopupTargetAnimationCurveProperty = null;
	
}

2、 AnimationCurveExtractor.cs

// Original code by: Joshua Glazer 
// Updated to Unity 4.3.4 by: Aurelio Provedo [aurelioprovedo@gmail.com]
using System;
using UnityEngine;
using UnityEditor;


public class AnimationCurveExtractor : EditorWindow
{
	
	
	public void Init(SerializedProperty inTargetProperty)
	{
		//keep the iterator in its current state...
		_PopupTargetAnimationCurveProperty = inTargetProperty;
	}
	
	void OnGUI()
	{
		AnimationClip anim = EditorGUILayout.ObjectField("Source Animation", _SourceAnimationClip, typeof(AnimationClip), false) as AnimationClip;
		
		if (anim != _SourceAnimationClip)
		{
			_SourceAnimationClip = anim;
			if (anim != null)
			{
				#if !UNITY_4_2
				_Curves = AnimationUtility.GetCurveBindings(anim);
				#else
				_Curves = AnimationUtility.GetAllCurves(anim);
				#endif
				
				_SelectedCurveIndex = 0;
				int curveCount = _Curves.Length;
				_CurveNames = new string[curveCount];
				for (int i = 0; i < curveCount; ++i)
				{
					if (_Curves[i].path == "")
					{
						_CurveNames[i] = _Curves[i].propertyName;
					}
					else
					{
						_CurveNames[i] = _Curves[i].path + "/" + _Curves[i].propertyName;
					}
				}
			}
			else
			{
				_Curves = null;
				_CurveNames = null;
			}
		}
		
		if (_Curves != null && _Curves.Length > 0)
		{
			_SelectedCurveIndex = EditorGUILayout.Popup("Source Curve", _SelectedCurveIndex, _CurveNames);
			
			#if !UNITY_4_2
			EditorGUILayout.CurveField("Data", AnimationUtility.GetEditorCurve(_SourceAnimationClip, _Curves[_SelectedCurveIndex]));
			#else
			EditorGUILayout.CurveField("Data", _Curves[_SelectedCurveIndex].curve);
			#endif
			
			/*
            _ShouldZeroOriginalCurve = EditorGUILayout.Toggle( "Should Zero Original Curve", _ShouldZeroOriginalCurve );
            */
			
			if (GUILayout.Button("Extract!"))
			{
				Extract();
				Close();
			}
		}
		
		
		
	}
	
	private void Extract()
	{
		#if !UNITY_4_2
		AnimationCurve sourceCurve = AnimationUtility.GetEditorCurve(_SourceAnimationClip, _Curves[_SelectedCurveIndex]);
		#else
		AnimationCurve sourceCurve = _Curves[_SelectedCurveIndex].curve;
		#endif
		
		_PopupTargetAnimationCurveProperty.animationCurveValue = AnimationCurveCopier.CreateCopy(sourceCurve);
		_PopupTargetAnimationCurveProperty.serializedObject.ApplyModifiedProperties();
		
		/*
         *we would need to copy this back in if we want it to work...
        if( _ShouldZeroOriginalCurve )
        {
            Keyframe[] keys = sourceCurve.keys;
            for( int i = 0, c = keys.Length; i < c; ++i )
            {
                keys[ i ].value = 0;
            }
            sourceCurve.keys = keys;
        }
        */
	}
	
	private SerializedProperty _PopupTargetAnimationCurveProperty;
	
	private AnimationClip _SourceAnimationClip;
	
	#if !UNITY_4_2
	private EditorCurveBinding[] _Curves;
	#else
	private AnimationClipCurveData[] _Curves;
	#endif
	
	private string[] _CurveNames;
	private int _SelectedCurveIndex;
	//private bool						_ShouldZeroOriginalCurve;
}


public static class AnimationCurveCopier
{
	public static void Copy(AnimationCurve inSource, AnimationCurve inDest)
	{
		inDest.keys = inSource.keys;
		inDest.preWrapMode = inSource.preWrapMode;
		inDest.postWrapMode = inSource.postWrapMode;
	}
	
	public static AnimationCurve CreateCopy(AnimationCurve inSource)
	{
		AnimationCurve newCurve = new AnimationCurve();
		Copy(inSource, newCurve);
		return newCurve;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值