https://blog.csdn.net/tlrainty/article/details/54602786

项目中经常会遇到这种情况:很多模型动画的AnimatorController是一模一样的(比如人类男,人类女),但是由于在AnimatorController中需要为每个State指定具体的Motion(比如人类女的Run和Attack要分别指定Human_Female_Run和Human_Female_Attack,如图1),我们并不能简单地在编辑器中给它们指定同一个AnimatorControllor,否则如果人类男用了人类女的AnimatorController我们就会发现人类男走起路来也一扭一扭的了=_=|||(原因是决定骨骼动画的Avatar信息存储在这个Motion所指定的AnimationClip中)

图1

要解决这个问题就要用到Unity的AnimatorOverrideController了,先贴个API手册: https://docs.unity3d.com/ScriptReference/AnimatorOverrideController.html

代码如下:

  1. private readonly string PrePath = "Prefabs/AnimationClips/";
  2. private readonly string[] ActionList = {"Run", "Attack"};
  3. private Animator m_animator = GetComponent<Animator>();
  4. <span style="white-space:pre;">   </span>[HideInInspector]
  5. public string m_modelName;
  6. //...
  7. if (m_animator != null)
  8. {
  9. AnimatorOverrideController overrideController = new AnimatorOverrideController();
  10. overrideController.runtimeAnimatorController = m_animator.runtimeAnimatorController;
  11. foreach (var actionName in ActionList)
  12. overrideController[actionName] = Resources.Load(PrePath + m_modelName + "_" + actionName) as AnimationClip;
  13. m_animator.runtimeAnimatorController = overrideController;
  14. }

这里主要需要注意的是

1. Resources.Load()的是以"模型名_动作名"格式命名的.anim文件,比如模型名是"Human_Female",动作名是"Run",那动画文件就是"Human_Femal_Run.anim".

2. overrideController中保存的是当前animator中所有用到的动画片段. overrideController[actionName] 的actionName是动画片段的名字,而不是State名字,即图1红框中的部分.我们并不对State进行任何操作,包括Motion中指定的动画片段的名字也不改变.因此创建AnimatorController的时候,需要先随便给每个State的Motion指定一个名字为actionName的动画,保证overrideController[actionName]存在,然后我们再用自己的AnimationClip去替换它.拿刚才的人类男和人类女举例来说,就是需要先给Run这个State指定一个名字为Run的动画,Attack这个State也要指定一个名字为Attack的动画.这里随便用谁的动画都可以,因为我们这里只是为了"让Dictionary中存在这个Key",以便后面我们用上述代码来替换.另外有一点要注意的是

  1. overrideController[actionName] = Resources.Load(PrePath + m_modelName + "_" + actionName) as AnimationClip;

这句会把所有State中的同名动画片段都替换掉.

3.这里把每个动作单独作为一个anim保存而不是统一存在一个FBX中读取的原因是Unity现在还不能在运行时创建Animation(图2是16年2月Unity论坛的官方回复,后面我也没有找到新消息说支持了).

 
 

图2

4. 这种方法保存出来的带animator的prefab的动画在编辑器中看会是错的,因为此时还没有加载正确的animator controller,想看正确的动画需要看最原始的FBX文件

P.S.从FBX中提取单一anim的方法:当把FBX截取出Clips之后

在Project视图中点开FBX后面的白三角就会出现这些动画片段,单击想要提取的anim然后按ctrl+D(即Duplicate)就会在同一文件夹下生成相应的anim文件

本文中所用Unity版本为5.4.1f1

 
=======================================================================================================================================================================================================================
【动态替换clip】
【动态添加动画事件】
using UnityEngine;
/// <summary>
/// 代码示例
/// </summary>
public class SetupAnimatorOverrideController : MonoBehaviour
{
public AnimationClip m_clip; private void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
Debug.Log("切换");
OverrideAnimationClip("suit03_Boy_idle", m_clip);
AddAnimEvent(m_clip);
}
} public RuntimeAnimatorController GetEffectiveController(Animator animator)
{
RuntimeAnimatorController controller = animator.runtimeAnimatorController; AnimatorOverrideController overrideController = controller as AnimatorOverrideController;
while (overrideController != null)
{
controller = overrideController.runtimeAnimatorController;
overrideController = controller as AnimatorOverrideController;
} return controller;
} /// <summary>
/// 动态替换clip
/// </summary>
/// <param name="name"></param>
/// <param name="clip"></param>
public void OverrideAnimationClip(string name, AnimationClip clip)
{
Animator animator = GetComponent<Animator>(); AnimatorOverrideController overrideController = new AnimatorOverrideController();
overrideController.runtimeAnimatorController = GetEffectiveController(animator);
overrideController[name] = clip;
animator.runtimeAnimatorController = overrideController;
} /// <summary>
/// 动态添加动态事件
/// </summary>
/// <param name="clip"></param>
public void AddAnimEvent(AnimationClip clip)
{
AnimationEvent aEvent1 = new AnimationEvent();
aEvent1.time = clip.length;
aEvent1.functionName = "OnOpenComplete";
clip.AddEvent(aEvent1);
} public void OnOpenComplete()
{
Debug.Log("呵呵");
}
}

=================================2018年5月24日20:10:14=======================================

/// 老版动画系统一些功能有所缺少(例如,不支持位移动画,会闪回)
/// 新版动画唯一坑爹的就是缺少动态去添加clip,只能把原有的clip替换成新的clip
/// 那么要想支持具有大量动画的游戏,有2种办法
/// 1.animator里面添加足够多的clip,以便于到时候随意替换,因为animator.Play("xx") 可以直接播放动画,不需要通过触发器
/// 2.构建一种三角形的万能架构(用于去支持流星的动态连招),直接动态变换clip

运行时用AnimatorOverrideController动态加载动画片段的更多相关文章

  1. Canvas——使用定时器模拟动态加载动画!

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  2. 【Vue】动态加载Html片段

    在编写Vue页面的时候,会碰到这么一个需求.由于页面组件比较多,不可能一次性将所有的页面都打包,只能按需获取相应的页面进行显示. 比如有一个App页面,需要异步获取html片段通过v-html指令加载 ...

  3. Ajaxload动态加载动画生成工具的实现(ajaxload的本地移植)

    前言 前段时间看到一个国外的网站,在线生成ajax loading动画.觉得很实用,于是动起了移植到自己网站的念头(一直以来的习惯,看到好的工具总想着移植到本地好好研究).根据以往移植的经验最终把 这 ...

  4. jQuery动态加载动画spin.js

    在线演示 本地下载

  5. WPF当属性值改变时利用PropertyChanged事件来加载动画

    在我们的程序中,有时我们需要当绑定到UI界面上的属性值发生变化从而引起数据更新的时候能够加载一些动画,从而使数据更新的效果更佳绚丽,在我们的程序中尽量将动画作为一种资源放在xaml中,而不是在后台中通 ...

  6. svg的animate动画动态加载删除遇到删除animate后再次加载的animate动画没有效果问题

    svg上有多个圆圈,当选中特定圆圈后给其加上animate动画效果,并把其他圆圈的animate效果去除. 第一次选择一个点实现动画效果完全达到效果,因为是第一次所以不需要把其他圆圈的animate子 ...

  7. unity动态加载(翻译) .

    AssetBundles are files which you can export from Unity to contain assets of your choice. These files ...

  8. Unity3D AssetBundles 动态加载游戏资源

    AssetBundles are files which you can export from Unity to contain assets of your choice. These files ...

  9. [AngularJS] 使用AngularCSS动态加载CSS

    [AngularJS] 使用AngularCSS动态加载CSS 前言 使用AngularAMD动态加载Controller 使用AngularAMD动态加载Service 上列两篇文章里,介绍了如何如 ...

随机推荐

  1. 15、Semantic-UI之导航

    15.1 面包屑导航   在Semantic-UI中有多种样式实现面包屑导航,类似 / > 等. 示例:定义定义基础面包屑导航 <div class="ui container& ...

  2. 20145233《网络对抗》Exp7 DNS网络欺诈技术防范

    20145233<网络对抗>Exp7 DNS网络欺诈技术防范 实验问题思考 通常在什么场景下容易受到DNS spoof攻击 公共的无线局域网中,容易受到攻击者的攻击,因为这样就会连入局域网 ...

  3. css3动画简单应用

    CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript.CSS3动画的属性主要分为三类:transform.transition以及anim ...

  4. SAH Benchmarks Of Natural History Museum Scene

    method                                                                                               ...

  5. 5个Shell脚本编程入门练习例子

    例子一:绘制特殊图形 复制代码代码如下: #!/bin/bash MAX_NO=0 echo -n "Enter Number between (5 to 9) : " read ...

  6. leetcode 19. 删除链表的倒数第N个节点 JAVA

    题目: 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链 ...

  7. Mysql数据类型《一》整数类型

    数值类型 1. 整数类型 整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT 作用:存储年龄,等级,id,各种号码等 ======================== ...

  8. BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

  9. 红黑树RBTree

    #pragma onceenum colour    //子节点的颜色{    RED,    BLANK,};template<class K,class V>struct RBTree ...

  10. ArchLinux 下文件描述符

    stderr -> /proc/self/fd/2 标准错误:2 stdin -> /proc/self/fd/0 标准输入:0 stdout -> /proc/self/fd/1 ...