Unity3D - Animator Controller循環依賴

問題html

假設有2個Animator Controller,分別命名爲TestControllerLhs.controller以及TestControllerRhs.controller。在TestControllerLhs.controller中設置狀態以下:工具

TestControllerLhs.controllerui

當拷貝了包含Transitions而且該Transitions的Dst State不存在的Animator State到另外一個Animator Controller時,就會出現遊離依賴數據。以TestControllerLhs.controller爲例,查看該文件可以發現,Attack01包含了Transitions數據:spa

Attack01包含的Transition3d

該Transition的Dst State爲Attack02。若是咱們拷貝Attack01但沒有拷貝Attack02到TestControllerRhs.controller,那麼就出現了遊離依賴數據:code

TestControllerRhs.controllerhtm

遊離依賴數據blog

出現依賴的緣由是該Transition的Dst State,即Attack02,仍然位於TestControllerLhs.controller中,沒有被拷貝過來。說該數據是遊離的緣由是在TestControllerRhs.controller中,咱們徹底看不見他,也沒法刪除它。ci

在這裏注意到這個問題的緣由是,美術在製做Animator Controller時常常會使用拷貝、黏貼的操做,很容易在無心間產生遊離依賴數據,而最關鍵也最嚴重的問題是循環依賴,即A.controller依賴B.controller,而且B.controller依賴A.controller。若是這兩個Controller都是AssetBundle的話,就會產生無限依賴加載。開發

解決方案

經過以前的遊離依賴數據分析可知他們的共性爲m_DstState項包含了所依賴的.controller文件的guid,所以咱們經過讀取.controller文件將這些遊離依賴數據刪除。
如下的代碼包含了檢測循環依賴,打印依賴的Animator Controller以及去除遊離依賴數據的功能,開發版本爲Unity 5.5.2f1:

  1 /******************************************************************************
  2  * DESCRIPTION: AnimatorController處理器
  3  * 
  4  *     Copyright (c) 2017, 譚偉俊 (TanWeijun)
  5  *     All rights reserved
  6  * 
  7  * COMPANY:
  8  * CREATED: 2017.09.20, 15:48, CST
  9 *******************************************************************************/
 10 
 11 using System.IO;
 12 using System.Collections.Generic;
 13 using UnityEngine;
 14 using UnityEditor;
 15 using UnityEditor.Animations;
 16 using GameFramework;
 17 
 18 public class AnimatorControllerProcessor
 19 {
 20     [MenuItem("Assets/Artist Tools/Animator Controller/Correct Data")]
 21     private static void CorrectData()
 22     {
 23         string block = null;
 24         bool isDependOtherAnimatorController = false;
 25         AnimatorController animatorController = Selection.activeObject as AnimatorController;
 26         string filePathName = Path.GetFullPath(AssetDatabase.GetAssetPath(animatorController));
 27         string tempFilePathName = Application.dataPath + "/" + System.DateTime.Now.Ticks.ToString() + ".controller";
 28         using (StreamWriter writer = File.CreateText(tempFilePathName))
 29         {
 30             using (StreamReader reader = File.OpenText(filePathName))
 31             {
 32                 string content;
 33                 while (null != (content = reader.ReadLine()))
 34                 {
 35                     if (content.StartsWith("--- !u"))
 36                     {
 37                         if (!string.IsNullOrEmpty(block))
 38                             writer.Write(block);
 39 
 40                         block = content + System.Environment.NewLine;
 41                         isDependOtherAnimatorController = false;
 42                     }
 43                     else
 44                     {
 45                         if (isDependOtherAnimatorController)
 46                             continue;
 47 
 48                         if (string.IsNullOrEmpty(block))
 49                             writer.WriteLine(content);
 50                         else
 51                         {
 52                             block += (content + System.Environment.NewLine);
 53 
 54                             // 檢測是否依賴其餘的Animator Controller
 55                             if (content.Contains("m_DstState:") && content.Contains("guid"))
 56                             {
 57                                 block = null;
 58                                 isDependOtherAnimatorController = true;
 59                             }
 60                         }
 61                     }
 62                 }
 63 
 64                 // 寫入最後的數據
 65                 if (!string.IsNullOrEmpty(block))
 66                     writer.Write(block);
 67             }
 68         }
 69 
 70         FileUtil.ReplaceFile(tempFilePathName, filePathName);
 71         AssetDatabase.Refresh();
 72     }
 73 
 74     [MenuItem("Assets/Artist Tools/Animator Controller/Collect Animator Controller Dependencies")]
 75     private static void CollectAnimatorControllerDependencies()
 76     {
 77         AnimatorController animatorController = Selection.activeObject as AnimatorController;
 78         string[] dependencyArray = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(animatorController));
 79 
 80         Log.Debug("************************* Animator Controller Dependencies (" + animatorController.name + ") *************************");
 81         foreach (string dependency in dependencyArray)
 82         {
 83             if (dependency.EndsWith(".controller"))
 84                 Log.Debug(dependency);
 85         }
 86         Log.Debug("************************************************* End *************************************************");
 87     }
 88 
 89     [MenuItem("ArtistTools/Check Animator Controller Dependencies")]
 90     private static void CheckAnimatorControllerDependencies()
 91     {
 92         List<string> dependencyCheckNameList = new List<string>();
 93         string[] filePathNameArray = Directory.GetFiles(Application.dataPath + "/BundleResources/Animator", "*.controller", SearchOption.TopDirectoryOnly);
 94         foreach (string filePathName in filePathNameArray)
 95         {
 96             string[] dependencyArray = AssetDatabase.GetDependencies(filePathName.Substring(filePathName.IndexOf("/Assets/") + 1));
 97             foreach (string dependency in dependencyArray)
 98             {
 99                 if (dependency.EndsWith(".controller"))
100                 {
101                     string assetName = Path.GetFileNameWithoutExtension(filePathName);
102                     string dependencyName = Path.GetFileNameWithoutExtension(dependency);
103 
104                     // A依賴於B,若是"B_A"存在,表示B也依賴於A,則是循環依賴
105                     string checkName = dependencyName + "_" + assetName;
106                     if (dependencyCheckNameList.Contains(checkName))
107                         Log.Debug(Path.GetFileName(filePathName) + " and " + Path.GetFileName(dependency) + " depend each other");
108 
109                     dependencyCheckNameList.Add(assetName + "_" + dependencyName);
110                 }
111             }
112         }
113     }
114 
115     [MenuItem("Assets/Artist Tools/Animator Controller/Correct Data", true)]
116     [MenuItem("Assets/Artist Tools/Animator Controller/Collect Animator Controller Dependencies", true)]
117     private static bool ValidateCorrectData()
118     {
119         return Selection.activeObject is AnimatorController;
120     }
121 }

打印依賴的Animator Controller:

TestControllerLhs依賴TestControllerRhs

TestControllerRhs依賴TestControllerLhs

檢測循環依賴:

循環依賴

使用工具清理遊離依賴數據後:

除了自身再也不依賴其餘的Animator Controller

 

本文固定連接: http://www.cnblogs.com/twjcnblog/p/7663048.html
轉載請註明: EnigmaJJ 2017年10月13日 於 cnblog 發表

相關文章
相關標籤/搜索