问题

假设有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 发表

Unity3D - Animator Controller循环依赖的更多相关文章

  1. Unity3D之Mecanim动画系统学习笔记(五):Animator Controller

    简介 Animator Controller在Unity中是作为一种单独的配置文件存在的文件类型,其后缀为controller,Animator Controller包含了以下几种功能: 可以对多个动 ...

  2. Animator Controller 继承关系

    准备知识 对于Animator Controller中蜘蛛网一样的几十条连线,后续如果靠人工维护,那成本将是很大. AnimatorOverrideController组件的文档:https://do ...

  3. Spring基础系列-Spring事务不生效的问题与循环依赖问题

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9476550.html 一.提出问题 不知道你是否遇到过这样的情况,在ssm框架中开发we ...

  4. service层代码相互调用, 导致spring循环依赖,设计上的优化

    管理员创建用户需要发送激活邮件, 而发送激活邮件的时候需要判断发件人是不是合法的用户, 因此设计到一个循环依赖的问题 //UserService @Service class UserService{ ...

  5. Spring Cloud杜绝循环依赖

    前言 大家在开发中有没有遇到过因循环依赖导致项目启动失败?在排查循环依赖的过程中有没困难?如何避免写出循环依赖的代码? 我没写过循环依赖的代码,作为稳定性负责人,我排查过多次. 有些逻辑简单的代码,循 ...

  6. .netcore ioc 循环依赖问题及其相关思考之DispatchProxy

    .netcore引入了ioc机制让开发人员逐步习惯从过去的各种new对象变成通过IOC框架来管理对象的生命周期.这样当我们需要某个对象的时候,我们一般在构造函数里申明该对象的接口,即可通过ioc容器创 ...

  7. SpringBoot项目意外出现 循环依赖和注入的对象意外是Null的问题 Requested bean is currently in creation: Is there an unresolvable circular reference? 或 nested exception is java.lang.NullPointerException

    1.Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ...

  8. kmdjs和循环依赖

    循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚.所以没解决好循环依赖的模块化库.框架.编译器都不是一个好 ...

  9. spring3 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

随机推荐

  1. 移动端rem使用

    let $html=document.documentElement,windowW = window.innerWidth,ratio = windowW / 750if (windowW > ...

  2. 对于c语言存储分配程序(malloc函数)实现的理解

    内容主要出自<The C Programming Language>一书,不得不说这是一本程序员必读的书,我大二读了前面几章就扔到一边了,直到最近才又拿起来再读,找不到言语来形容我现在后悔 ...

  3. 英语学习APP案例分析

    第一部分 调研, 评测 1.上手体验 界面简洁,有常规的词典翻译功能,针对四六级或考研的人有特别的"单词挑战"模块,以及针对口语训练的"我爱说英语"模块,多功能 ...

  4. 【2017集美大学1412软工实践_助教博客】团队作业3——需求改进&系统设计 成绩公示

    第三次团队作业成绩公布 题目 团队作业3: 需求改进&系统设计 团队成绩 成绩公示如下: 缩写 TD BZ GJ CJ SI WBS GS JG DB SS SJ CS DC Total 分值 ...

  5. 【Alpha】第七次Daily Scrum Meeting

    GIT 一.今日站立式会议照片        二.会议内容 1.讨论送礼物的方法和对象,使功能更加完善. 2.对于程序还存在的问题提出自己的看法,尽量让功能更加的饱满. 三.燃尽图 四.遇到的困难 能 ...

  6. Swing-JCheckBox用法-入门

    JCheckBox是Swing中的复选框.所谓复选框就是指,可以同时存在多个这样的控件,它们可以有多个处于被选中状态.对于每一个复选框而言,它只有选中和未选中两种状态. JCheckBox的常用方法如 ...

  7. 201521123038 《Java程序设计》 第一周学习总结

    201521123038 <Java程序设计> 第一周学习总结 1.本章学习总结 本周已掌握Java配置,初步认识Java运行软件和基本语法. Java语言语法和C语言基本类似,部分不同. ...

  8. ArrayList和LinkedList区别及性能测试

    ArrayList和LinkedList是Java Lis接口的2个实现.它们的区别如下表所示: 底层结构 强项 弱项 ArrayList 数组 随机访问get和set 插入删除 LinkedList ...

  9. 201521123106 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  10. 201521123022 《Java程序设计》 第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 Q1.finally 题目4-2 Q1.1 截图你的提交结果 ...