Unity3D - Animator Controller循环依赖
问题
假设有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循环依赖的更多相关文章
- Unity3D之Mecanim动画系统学习笔记(五):Animator Controller
简介 Animator Controller在Unity中是作为一种单独的配置文件存在的文件类型,其后缀为controller,Animator Controller包含了以下几种功能: 可以对多个动 ...
- Animator Controller 继承关系
准备知识 对于Animator Controller中蜘蛛网一样的几十条连线,后续如果靠人工维护,那成本将是很大. AnimatorOverrideController组件的文档:https://do ...
- Spring基础系列-Spring事务不生效的问题与循环依赖问题
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9476550.html 一.提出问题 不知道你是否遇到过这样的情况,在ssm框架中开发we ...
- service层代码相互调用, 导致spring循环依赖,设计上的优化
管理员创建用户需要发送激活邮件, 而发送激活邮件的时候需要判断发件人是不是合法的用户, 因此设计到一个循环依赖的问题 //UserService @Service class UserService{ ...
- Spring Cloud杜绝循环依赖
前言 大家在开发中有没有遇到过因循环依赖导致项目启动失败?在排查循环依赖的过程中有没困难?如何避免写出循环依赖的代码? 我没写过循环依赖的代码,作为稳定性负责人,我排查过多次. 有些逻辑简单的代码,循 ...
- .netcore ioc 循环依赖问题及其相关思考之DispatchProxy
.netcore引入了ioc机制让开发人员逐步习惯从过去的各种new对象变成通过IOC框架来管理对象的生命周期.这样当我们需要某个对象的时候,我们一般在构造函数里申明该对象的接口,即可通过ioc容器创 ...
- 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 ...
- kmdjs和循环依赖
循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚.所以没解决好循环依赖的模块化库.框架.编译器都不是一个好 ...
- spring3 循环依赖
循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...
随机推荐
- 移动端rem使用
let $html=document.documentElement,windowW = window.innerWidth,ratio = windowW / 750if (windowW > ...
- 对于c语言存储分配程序(malloc函数)实现的理解
内容主要出自<The C Programming Language>一书,不得不说这是一本程序员必读的书,我大二读了前面几章就扔到一边了,直到最近才又拿起来再读,找不到言语来形容我现在后悔 ...
- 英语学习APP案例分析
第一部分 调研, 评测 1.上手体验 界面简洁,有常规的词典翻译功能,针对四六级或考研的人有特别的"单词挑战"模块,以及针对口语训练的"我爱说英语"模块,多功能 ...
- 【2017集美大学1412软工实践_助教博客】团队作业3——需求改进&系统设计 成绩公示
第三次团队作业成绩公布 题目 团队作业3: 需求改进&系统设计 团队成绩 成绩公示如下: 缩写 TD BZ GJ CJ SI WBS GS JG DB SS SJ CS DC Total 分值 ...
- 【Alpha】第七次Daily Scrum Meeting
GIT 一.今日站立式会议照片 二.会议内容 1.讨论送礼物的方法和对象,使功能更加完善. 2.对于程序还存在的问题提出自己的看法,尽量让功能更加的饱满. 三.燃尽图 四.遇到的困难 能 ...
- Swing-JCheckBox用法-入门
JCheckBox是Swing中的复选框.所谓复选框就是指,可以同时存在多个这样的控件,它们可以有多个处于被选中状态.对于每一个复选框而言,它只有选中和未选中两种状态. JCheckBox的常用方法如 ...
- 201521123038 《Java程序设计》 第一周学习总结
201521123038 <Java程序设计> 第一周学习总结 1.本章学习总结 本周已掌握Java配置,初步认识Java运行软件和基本语法. Java语言语法和C语言基本类似,部分不同. ...
- ArrayList和LinkedList区别及性能测试
ArrayList和LinkedList是Java Lis接口的2个实现.它们的区别如下表所示: 底层结构 强项 弱项 ArrayList 数组 随机访问get和set 插入删除 LinkedList ...
- 201521123106 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...
- 201521123022 《Java程序设计》 第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 Q1.finally 题目4-2 Q1.1 截图你的提交结果 ...