问题

假设有2个Animator Controller,分别命名为TestControllerLhs.controller以及TestControllerRhs.controller。在TestControllerLhs.controller中设置状态如下:

TestControllerLhs.controller

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

Attack01包含的Transition

该Transition的Dst State为Attack02。如果我们拷贝Attack01但没有拷贝Attack02到TestControllerRhs.controller,那么就出现了游离依赖数据:

TestControllerRhs.controller

游离依赖数据

出现依赖的原因是该Transition的Dst State,即Attack02,仍然位于TestControllerLhs.controller中,没有被拷贝过来。说该数据是游离的原因是在TestControllerRhs.controller中,我们完全看不见他,也无法删除它。

在这里注意到这个问题的原因是,美术在制作Animator Controller时经常会使用拷贝、黏贴的操作,很容易在无意间产生游离依赖数据,而最关键也最严重的问题是循环依赖,即A.controller依赖B.controller,并且B.controller依赖A.controller。如果这两个Controller都是AssetBundle的话,就会产生无限依赖加载。

解决方案

通过之前的游离依赖数据分析可知他们的共性为m_DstState项包含了所依赖的.controller文件的guid,因此我们通过读取.controller文件将这些游离依赖数据删除。
以下的代码包含了检测循环依赖,打印依赖的Animator Controller以及去除游离依赖数据的功能,开发版本为Unity 5.5.2f1:

 /******************************************************************************
* DESCRIPTION: AnimatorController处理器
*
* Copyright (c) 2017, 谭伟俊 (TanWeijun)
* All rights reserved
*
* COMPANY:
* CREATED: 2017.09.20, 15:48, CST
*******************************************************************************/ using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using GameFramework; public class AnimatorControllerProcessor
{
[MenuItem("Assets/Artist Tools/Animator Controller/Correct Data")]
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); // 检测是否依赖其他的Animator Controller
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("Assets/Artist Tools/Animator Controller/Collect Animator Controller Dependencies")]
private static void CollectAnimatorControllerDependencies()
{
AnimatorController animatorController = Selection.activeObject as AnimatorController;
string[] dependencyArray = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(animatorController)); Log.Debug("************************* Animator Controller Dependencies (" + animatorController.name + ") *************************");
foreach (string dependency in dependencyArray)
{
if (dependency.EndsWith(".controller"))
Log.Debug(dependency);
}
Log.Debug("************************************************* End *************************************************");
} [MenuItem("ArtistTools/Check Animator Controller Dependencies")]
private static void CheckAnimatorControllerDependencies()
{
List<string> dependencyCheckNameList = new List<string>();
string[] filePathNameArray = Directory.GetFiles(Application.dataPath + "/BundleResources/Animator", "*.controller", SearchOption.TopDirectoryOnly);
foreach (string filePathName in filePathNameArray)
{
string[] dependencyArray = AssetDatabase.GetDependencies(filePathName.Substring(filePathName.IndexOf("/Assets/") + ));
foreach (string dependency in dependencyArray)
{
if (dependency.EndsWith(".controller"))
{
string assetName = Path.GetFileNameWithoutExtension(filePathName);
string dependencyName = Path.GetFileNameWithoutExtension(dependency); // A依赖于B,如果"B_A"存在,表示B也依赖于A,则是循环依赖
string checkName = dependencyName + "_" + assetName;
if (dependencyCheckNameList.Contains(checkName))
Log.Debug(Path.GetFileName(filePathName) + " and " + Path.GetFileName(dependency) + " depend each other"); dependencyCheckNameList.Add(assetName + "_" + dependencyName);
}
}
}
} [MenuItem("Assets/Artist Tools/Animator Controller/Correct Data", true)]
[MenuItem("Assets/Artist Tools/Animator Controller/Collect Animator Controller Dependencies", true)]
private static bool ValidateCorrectData()
{
return Selection.activeObject is AnimatorController;
}
}

打印依赖的Animator Controller:

TestControllerLhs依赖TestControllerRhs

TestControllerRhs依赖TestControllerLhs

检测循环依赖:

循环依赖

使用工具清理游离依赖数据后:

除了自身不再依赖其他的Animator Controller

本文固定链接: http://www.cnblogs.com/twjcnblog/p/7663048.html
转载请注明: EnigmaJJ 2017年10月13日 于 cnblog 发表

最新文章

  1. 特征的SID表、M表、P表、Q表、X表、Y表、T表
  2. Scrum2.0 项目基本完成
  3. 使用@ContextConfiguration注解后,提示找不到配置文件
  4. 最全的C#图片处理帮助类ImageHelper
  5. hdu4474 Yet Another Multiple Problem
  6. localStorage与location的用法
  7. Fitnesse - Slim Tables
  8. Linux之批量挂载硬盘
  9. 阿里云 云服务器 CentOS 5.8 安装 php 5.4
  10. 设计模式之Singleton模式和Strategy模式是什么
  11. mysql语句将日期转换为时间戳的方法
  12. c#多线程thread实例详解
  13. bzoj5108: [CodePlus2017]可做题
  14. [CB转帖]台湾晶圆厂产能居全球第一 大陆排名第五但增长最多
  15. java学习笔记25(Collections类)
  16. redis keys 命令
  17. 【20181030T2】字胡串【分治+双指针】
  18. 阿里杨传辉的访问节选(oceanbase)
  19. oracle中空值null的判断和转换:NVL的用法
  20. 从hive导入到oracle(Hcatalog)

热门文章

  1. 只查看tomcat进程,不包括grep
  2. YYHS-NOIP2017SummerTraining0914-问题 A: 组合数问题
  3. 1011. A+B和C (15)
  4. 转: 【Java并发编程】之十七:深入Java内存模型—内存操作规则总结
  5. 第四次作业 四则运算器在C++层面上的进一步思考
  6. 201521123056 《Java程序设计》第7周学习总结
  7. 201521123004 《Java程序设计》第 14 周学习总结
  8. Java课程设计——学生信息系统(团队)
  9. Java程序设计——学生信息系统
  10. 201521123014 《Java程序设计》第10周学习总结