Unity 的 Animator Controller 在游戏中一般用来做动画状态机,存放一个游戏中人物或物体的各种动画,便于程序调用。
由于很多人物的动画状态机结构基本一致,我们在使用时常常直接复制 Animator Controller 或者复制其中的节点到另外一个 Animator Controller 中。
但实际操作中,这样会产生冗余数据和不必要的引用关系。
问题

如图,在导出名为12100的Animator Controller 时,选择包含引用时,会同时导出名为17001的Animator Controller。
然而实际上打开12100,视图里面并没有17001的animation节点,即使把所有节点都删除再保存,重新导出依然有17001的引用。
查找guid
打开17001的meta文件,找到它的guid,然后在12100的Controller文件中搜索,可以发现一个AnimatorStateTransition关联了这个guid。

关联的内容是:
1 2
   | m_DstState: {fileID: 1102131212858548580, guid: df538bb3c58384d4b83ab1cdbb708854,     type: 2}
  | 
 
改成:
这样再保存,引用关系就解除了。
再次导出就没有多余的引用了。

原因
这个问题产生的原因是复制17001,在此基础上制作了12001,因此12001包含了17001的引用。
上面是大概的原因,下面讲一下冗余依赖产生的具体原因。
假如有两个Animator Controller 文件,分别名为a.controller和b.controller 。
a.controller 中的状态如下:

可以看到Attack01指向Attack02。
当拷贝了包含Transitions并且该Transitions的Dst State不存在的Animator State到另一个Animator Controller时,就会出现游离依赖数据。以a.controller为例,查看该文件能够发现Attack01节点包含的Transitions数据:

该Transition的Dst State为Attack02。如果我们拷贝Attack01但没有拷贝Attack02到b.controller,那么b.controller中就出现了游离依赖数据m_DstState。
并且这个数据我们在视图中看不到,也删不掉,随着拷贝次数增加,冗余数据会越来越多,甚至会造成循环依赖。如果这两个Controller都是AssetBundle的话,就会产生无限依赖加载。
解决办法
手工
不使用直接复制来制作新的Animator Controller ,只通过工具生成空的Animator Controller 。
在遇到冗余引用时,暂时只能找到荣誉动画的meta,找到guid然后再有冗余的Controller中查找删除。
如果是引用了多余的Animator Controller:
如果是引用了多余的Animation:
脚本
通过之前的游离依赖数据分析可知他们的共性为m_DstState项包含了所依赖的.controller文件的guid,因此我们可以通过读取.controller文件将这些游离依赖数据删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
   | using System.IO; using System.Collections.Generic; using UnityEngine; using UnityEditor; using UnityEditor.Animations;
  public class AnimatorChecker {     [MenuItem("美术工具/Animator Controller/清除冗余引用数据")]     private static void CorrectData()     {         string block = null;         bool isDependOtherAnimatorController = false;         AnimatorController animatorController = Selection.activeObject as AnimatorController;         string filePathName = Path.GetFullPath(AssetDatabase.GetAssetPath(animatorController));         string tempFilePathName = Application.dataPath + "/" + System.DateTime.Now.Ticks.ToString() + ".controller";         using (StreamWriter writer = File.CreateText(tempFilePathName))         {             using (StreamReader reader = File.OpenText(filePathName))             {                 string content;                 while (null != (content = reader.ReadLine()))                 {                     if (content.StartsWith("--- !u"))                     {                         if (!string.IsNullOrEmpty(block))                             writer.Write(block);
                          block = content + System.Environment.NewLine;                         isDependOtherAnimatorController = false;                     }                     else                     {                         if (isDependOtherAnimatorController)                             continue;
                          if (string.IsNullOrEmpty(block))                             writer.WriteLine(content);                         else                         {                             block += (content + System.Environment.NewLine);
                                                           if (content.Contains("m_DstState:") && content.Contains("guid"))                             {                                 block = null;                                 isDependOtherAnimatorController = true;                             }                         }                     }                 }
                                   if (!string.IsNullOrEmpty(block))                     writer.Write(block);             }         }
          FileUtil.ReplaceFile(tempFilePathName, filePathName);         AssetDatabase.Refresh();     }
      [MenuItem("美术工具/Animator Controller/查找Animator Controller引用")]     private static void CollectAnimatorControllerDependencies()     {         AnimatorController animatorController = Selection.activeObject as AnimatorController;         string[] dependencyArray = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(animatorController));
          Debug.Log("************************* Animator Controller Dependencies (" + animatorController.name + ") *************************");         foreach (string dependency in dependencyArray)         {             if (dependency.EndsWith(".controller"))                 Debug.Log(dependency);         }         Debug.Log("************************************************* End *************************************************");     }
      [MenuItem("美术工具/Animator Controller/查找所有Animator Controller引用")]     private static void CheckAnimatorControllerDependencies()     {         List<string> dependencyCheckNameList = new List<string>();         string[] filePathNameArray = Directory.GetFiles(Application.dataPath + "/Content/Animator", "*.controller", SearchOption.TopDirectoryOnly);         foreach (string filePathName in filePathNameArray)         {             string[] dependencyArray = AssetDatabase.GetDependencies(filePathName.Substring(filePathName.IndexOf("/Assets/") + 1));             foreach (string dependency in dependencyArray)             {                 if (dependency.EndsWith(".controller"))                 {                     string assetName = Path.GetFileNameWithoutExtension(filePathName);                     string dependencyName = Path.GetFileNameWithoutExtension(dependency);
                                           string checkName = dependencyName + "_" + assetName;                     if (dependencyCheckNameList.Contains(checkName))                         Debug.Log(Path.GetFileName(filePathName) + " and " + Path.GetFileName(dependency) + " depend each other");
                      dependencyCheckNameList.Add(assetName + "_" + dependencyName);                 }             }         }     }
      [MenuItem("美术工具/Animator Controller/清除冗余引用数据", true)]     [MenuItem("美术工具/Animator Controller/查找Animator Controller引用", true)]     private static bool ValidateCorrectData()     {         return Selection.activeObject is AnimatorController;     } }
   | 
 
参考
https://www.cnblogs.com/twjcnblog/p/7663048.html