問題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 發表