參考文章:
Unity中將Animation Clip嵌入Animator Controller的方法
??我要做這個(gè)工具的原因,跟參考文章類(lèi)似,偶然發(fā)現(xiàn)項(xiàng)目中有的Clip跟Controller是一個(gè)整體,這種方式比較方便管理簡(jiǎn)單動(dòng)畫(huà),所以搜了下創(chuàng)建方案。
??這里又造輪子,主要是拓展功能與修復(fù)參考文章的Bug,代碼都在下面,拓展的內(nèi)容是:
- 增加刪除某個(gè)內(nèi)嵌Clip的功能
- 修復(fù)Bug:參考文章中,Clip內(nèi)嵌到Controller后,Controller中動(dòng)畫(huà)狀態(tài)Motion并沒(méi)有跟Clip關(guān)聯(lián)起來(lái)
- 性能小優(yōu)化:內(nèi)嵌過(guò)程中,沒(méi)必要重新導(dǎo)入每個(gè)Clip,再最后執(zhí)行一次即可(因?yàn)槊看沃匦聦?dǎo)入的都是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,否則會(huì)導(dǎo)致動(dòng)畫(huà)狀態(tài)錯(cuò)亂
if(!ctrlPath.EndsWith(".controller")) return;
AssetDatabase.RemoveObjectFromAsset(clip);
Object.DestroyImmediate(clip);
AssetDatabase.SaveAssets();
}
/// <summary>
/// 替換動(dòng)畫(huà)控制器中使用的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;
}
}
}
}