Animator override Controller 是依托于Animator 使用的,应用于相同的动画逻辑,但是根据不同的对象,使用不同的动画clip
创建方法:在project视图中 create->
指定所要绑定的原始animator,并且对应原始animator上的clip指定代替的clip。
运行起来之后,挂载Animator override Controller 则会使用指定的clip替换原有动作。
例如动作可以复用,但是表情不同的情况下则可以使用Animator override Controller,近行区分。
数量较大的时候,最好使用编辑器脚本自动处理。
简单的示例(夹杂了一些当前项目中的设置,没来及全都拆干净)
using UnityEngine; using UnityEditor; using System.IO; using System.Collections.Generic; using System.Linq; using Object = UnityEngine.Object; public class AutoOverrideAnimator { //菜单 [MenuItem("Tools/setAnim")] public static void AutoSetAnim() { //获取选中的目标 Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); Dictionary<string, AnimationClip> commonClips = new Dictionary<string, AnimationClip>(); Dictionary<string, ModelImporter> commonModels = new Dictionary<string, ModelImporter>(); //动画路径 string path = "Assets/GameAssets/Animations/common"; if (Directory.Exists(path)) { DirectoryInfo direction = new DirectoryInfo(path); FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories); //加载所有的动画clip foreach (var file in files) { AnimationClip clip = AssetDatabase.LoadAssetAtPath(path + "/" + file.Name, typeof(AnimationClip)) as AnimationClip; if (clip) { if (!commonClips.ContainsKey(clip.name)) commonClips.Add(clip.name, clip); else //有重复的clip名时logError Debug.LogError("same key :" + clip.name + ":" + file.Name); } //加载 ModelImporter 用于确认动画长度等参数。 var model = ModelImporter.GetAtPath(path + "/" + file.Name) as ModelImporter; if (!model) continue; if (clip != null && !commonModels.ContainsKey(clip.name)) { commonModels.Add(clip.name,model); } } } foreach (var obj in selection) { if(obj is AnimatorOverrideController) { //根据明明方式近行 分割 string key = obj.name.Split(' ')[1]; Debug.LogError(key); path = "Assets/GameAssets/puppy/Animations/" + key; string commonPath = "Assets/GameAssets/puppy/Animations/common"; Dictionary<string, AnimationClip> clips = new Dictionary<string, AnimationClip>(); AnimatorOverrideController contro = (AnimatorOverrideController)obj; AnimationClipOverrides clipOverrides = new AnimationClipOverrides(contro.overridesCount); contro.GetOverrides(clipOverrides); AnimationClip[] useClips = contro.animationClips; List<string> useNames = useClips.Select(useClip => useClip.name).ToList(); if (Directory.Exists(path)) { DirectoryInfo direction = new DirectoryInfo(path); FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories); foreach(var file in files) { AnimationClip clip = AssetDatabase.LoadAssetAtPath(path + "/" + file.Name, typeof(AnimationClip)) as AnimationClip; if (clip) { if (!useNames.Contains(clip.name)) { continue; } if (!clips.ContainsKey(clip.name)) clips.Add(clip.name, clip); else Debug.LogError("same key :"+clip.name +":"+ file.Name); var strs = clip.name.Split('_'); if (strs[strs.Length - 1] != "h") continue; var bName = clip.name.Substring(0, clip.name.Length - 1) + 'b'; if (!commonClips.ContainsKey(bName)) continue; float bLastFrame = 0; float hLastFrame = 0; var model = ModelImporter.GetAtPath(path + "/" + file.Name) as ModelImporter; if (model != null && model.clipAnimations[0]!=null) { hLastFrame = model.clipAnimations[0].lastFrame; } ModelImporter bmodel = null; if (commonModels.ContainsKey(bName)) { bmodel = commonModels[bName]; bLastFrame = bmodel.clipAnimations[0].lastFrame; } if (model!=null&&bmodel!=null&&bLastFrame!=0f&&hLastFrame!=0f&&bLastFrame!=hLastFrame) { var bname = bmodel.assetPath.Split('/'); var hname = model.assetPath.Split('/'); Debug.LogError(key +":"+ clip.name + " animation length dose not Match! " + bname[bname.Length-1]+"frame:"+bLastFrame+"--"+hname[hname.Length-1]+"frame:"+hLastFrame); } } } } for(int i=0;i< useClips.Length;i++) { AnimationClip cp; if (clips.TryGetValue(useClips[i].name,out cp)) { clipOverrides[useClips[i].name] = cp; } else if(commonClips.TryGetValue(useClips[i].name, out cp)) { clipOverrides[useClips[i].name] = cp; } if (cp == null) { Debug.LogError("Can not found "+ key + ":"+ useClips[i].name); } } contro.ApplyOverrides(clipOverrides); } } AssetDatabase.SaveAssets(); } public class AnimationClipOverrides : List<KeyValuePair<AnimationClip, AnimationClip>> { public AnimationClipOverrides(int capacity) : base(capacity) { } public AnimationClip this[string name] { get { return this.Find(x => x.Key.name.Equals(name)).Value; } set { int index = this.FindIndex(x => x.Key.name.Equals(name)); if (index != -1) this[index] = new KeyValuePair<AnimationClip, AnimationClip>(this[index].Key, value); } } } }