[Unity Editor]将Animation Clip嵌入A
2020-06-11 本文已影响0人
_Walker__
参考文章:
Unity中将Animation Clip嵌入Animator Controller的方法
我要做这个工具的原因,跟参考文章类似,偶然发现项目中有的Clip跟Controller是一个整体,这种方式比较方便管理简单动画,所以搜了下创建方案。
这里又造轮子,主要是拓展功能与修复参考文章的Bug,代码都在下面,拓展的内容是:
- 增加删除某个内嵌Clip的功能
- 修复Bug:参考文章中,Clip内嵌到Controller后,Controller中动画状态Motion并没有跟Clip关联起来
- 性能小优化:内嵌过程中,没必要重新导入每个Clip,再最后执行一次即可(因为每次重新导入的都是Controller)
[MenuItem("Assets/Anime/Nest Clips in Controller")]
public static void NestAnimClips()
{
AnimatorController ctrl = Selection.activeObject as AnimatorController;
if (null == ctrl) return;
AnimationClip[] clips = ctrl.animationClips;
for (int i = 0; i < clips.Length; ++i)
{
AnimationClip clip = clips[i];
var assetPath = AssetDatabase.GetAssetPath(clip);
if (assetPath.EndsWith(".anim"))
{
AnimationClip newClip = Object.Instantiate(clip);
newClip.name = clip.name;
AssetDatabase.AddObjectToAsset(newClip, ctrl);
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(clip));
ReplaceStateMotion(ctrl, clip, newClip);
}
}
AssetDatabase.SaveAssets();
}
[MenuItem("Assets/Anime/Remove Nest Clip")]
public static void RemoveNestAnimClip()
{
AnimationClip clip = Selection.activeObject as AnimationClip;
if(clip == null) return;
string ctrlPath = AssetDatabase.GetAssetPath(clip);
// 保证只移除嵌套的clip,否则会导致动画状态错乱
if(!ctrlPath.EndsWith(".controller")) return;
AssetDatabase.RemoveObjectFromAsset(clip);
Object.DestroyImmediate(clip);
AssetDatabase.SaveAssets();
}
/// <summary>
/// 替换动画控制器中使用的Clip
/// </summary>
public static void ReplaceStateMotion(AnimatorController ctrl, AnimationClip oldClip, AnimationClip newClip, bool replaceAll=false)
{
foreach (AnimatorControllerLayer layer in ctrl.layers)
{
foreach (ChildAnimatorState childState in layer.stateMachine.states)
{
if (childState.state.motion == oldClip)
{
ctrl.SetStateEffectiveMotion(childState.state, newClip);
if (!replaceAll) return;
}
}
}
}