[Unity]运行时用AnimatorOverrideController动态加载动画片段
2017-01-18 17:58
501 查看
项目中经常会遇到这种情况:很多模型动画的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. 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",以便后面我们用上述代码来替换.另外有一点要注意的是
这句会把所有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
图1
要解决这个问题就要用到Unity的AnimatorOverrideController了,先贴个API手册: https://docs.unity3d.com/ScriptReference/AnimatorOverrideController.html
代码如下:
private readonly string PrePath = "Prefabs/AnimationClips/"; private readonly string[] ActionList = {"Run", "Attack"}; private Animator m_animator = GetComponent<Animator>(); [HideInInspector] public string m_modelName; //... if (m_animator != null) { AnimatorOverrideController overrideController = new AnimatorOverrideController(); overrideController.runtimeAnimatorController = m_animator.runtimeAnimatorController; foreach (var actionName in ActionList) overrideController[actionName] = Resources.Load(PrePath + m_modelName + "_" + actionName) as AnimationClip; m_animator.runtimeAnimatorController = overrideController; }
这里主要需要注意的是
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",以便后面我们用上述代码来替换.另外有一点要注意的是
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
相关文章推荐
- Unity5 LightMap 动态加载 运行时lightmapScaleOffset赋值后不生效
- unity动态加载Animator的Controller
- 第三方登录、动态的加载提示和点击效果、属性动画ObjectAnimator心得
- Unity加载模块深度解析之动画片段
- Unity中获取Animator中动画片段的时长
- 异步动态加载JS 并运行
- iPhone开发【十三】动画效果之最简单的动画——动态加载图片
- Poco共享库(加载共享库与运行时动态创建实例)
- silverlight如何在运行时用代码动态控制(或创建)动画
- 利用反射动态(运行时)加载窗体
- unity基础开发--实现动态加载资源
- unity基础开发-- 动态加载游戏对象或文件
- JAVA运行时动态加载类
- linux动态链接库中函数的运行时加载
- Unity动态(Runtime)加载脚本
- Frame动画的两种方法(写死的Xml与SD卡图片动态加载)
- Android开发之动态加载,运行未安装apk
- java 动态编译.java文件,然后动态加载运行
- silverlight如何在运行时用代码动态控制(或创建)动画
- 如何运行时(动态)加载js脚本|JavaScript