http://blog.csdn.net/langresser_king/article/details/37760091?utm_source=tuicool&utm_medium=referral

Unity的新动画系统Mecanim出来也有一阵子了,我的第一个Unity项目就是使用这个动画系统。但是只是做了最基本的应用,没有做深入的研究。

Mecanim的好处有三点:1、动画重定向,可以最大程度的复用动画资源   2、可视化编辑的状态机    3、Blend Tree可以方便的做动画融合,例如一边跑一边攻击。

但是对于我而言,Mecanim在使用上感觉有些蹩脚,最大的问题就是在可视化的状态机编辑上了。 这个状态机让动画编辑变得容易了,不需要一行代码就可以控制动作的流转,像Temple Run这样的游戏可以轻松搞定。  但是问题是,一个大型的mmo动画文件成百上千,如果都依托于这个编辑器的话,那状态机会变得像蜘蛛网一样密密麻麻,不可维护。更何况,连几千条线来处理动画,只有脑子抽疯的人才会这么干。

举个例子,人物有站立动画,拿不同武器的时候站立动作不一样,比如双持站立、空手站立、拿枪站立、拿弓站立等等;同样,跑步的动画也有十几种;死亡动画亦然。最后再加上几十个技能动画。这里我们不考虑骑马、马上攻击、飞行等等情况,可以算是简化的ARPG,但是即便如此,动画文件依然可能有一百多个。如果是按正常情况的话,光站立动作到技能就可能需要一千条线,每条线还要选择好正确的参数。正常人都应该意识到,这是不合理的。

解决方案一:

使用Mecanim Control插件,这个插件使用Mecanim系统提供的接口来模拟老式动画系统的接口(Play CrossFade等等)。把动画文件(Animation Clip)拖动到脚本上,然后就可以正常的使用Play等接口来进行动画播放了。由于内部依然使用的是Mecanim系统,所以支持动画重定向。如果没有什么特殊需求的话,这个应该是相对完善的解决方案。

要说缺点的话,也有一些,就是动画文件的流转完全交由代码来控制,并且不支持BlendTree动画融合。

解决方案二:

这个我还在初步尝试,理论上可行。 这个方案完全依托于Mecanim的操作方式和思路。只不过通过一些小技巧和没有广为流传的知识点使得Mecanim的编辑操作大大简化。

Mecanim 的状态机之所以变得复杂是因为多个站立动作与跑步动作以及技能之间的流转,这需要添加上千条线,而之所以会变得那么多,是因为站立动作本身就有十几个。如果有一种方法能够让十几个休闲动作作为一个整体去跟技能动作进行交互,那么连线数目直接降至几十条。 事实上,在Unity5里面会提供State Machine到State Machine之间的连线交互,每个Sub State Machine都有一个入口和出口,这就是我想要的。  可以再Unity4里面,Sub State Machine只是一个类似文件夹的概念,我们只能处理State之间的连线。

第一个知识点,通过animator.runtimeAnimatorController动态的替换动画控制器,通过AnimatorOverrideController动态的替换一个动画文件。 这个技术就是Mecanim Control插件所使用的。所以,我们只需要在状态机中添加一个Idle状态,然后控制这个状态和技能之间的动作流转。在代码中根据装备的武器动态的改变Idle的对应动画,然后就可以达到我们的目的了。参考代码如下:

[csharp] view
plain
 copy

  1. private Animator animator;
  2. public AnimationClip clip;
  3. // Use this for initialization
  4. void Start () {
  5. animator = GetComponent<Animator>();
  6. AnimatorOverrideController col = new AnimatorOverrideController();
  7. col.runtimeAnimatorController = animator.runtimeAnimatorController;
  8. col["2HAxe1"] = clip;
  9. animator.runtimeAnimatorController = col;
  10. }

第二个知识点,我们可以通过UnityEditorInternal.AnimatorController在编辑器中使用代码来创建AnimatorController文件,理论上也可加载并编辑一个controller文件。所以添加参数,添加动画文件,动画文件之间的连线这些体力活都可以使用脚本自动化完成。具体参考雨松的博客:http://www.xuanyusong.com/archives/2811

参考代码如下:

[csharp] view
plain
 copy

  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditorInternal;
  4. using System.Collections;
  5. public class AutoCreateAnimator : Editor {
  6. [MenuItem("Tools/创建动画控制器")]
  7. static void CreateAnimator()
  8. {
  9. //创建animationController文件,保存在Assets路径下
  10. AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath("Assets/animation.controller");
  11. //得到它的Layer, 默认layer为base 你可以去拓展
  12. AnimatorControllerLayer layer = animatorController.GetLayer(0);
  13. //把动画文件保存在我们创建的AnimationController中
  14. AddStateTransition("Assets/Model/Media/player/human_f/attack/human_f_2haxe1.fbx",layer);
  15. AddStateTransition("Assets/Model/Media/player/human_f/attack/human_f_2haxe2.fbx",layer);
  16. AddStateTransition("Assets/Model/Media/player/human_f/attack/human_f_2haxe3.fbx",layer);
  17. }
  18. private static void AddStateTransition(string path, AnimatorControllerLayer layer)
  19. {
  20. UnityEditorInternal.StateMachine sm = layer.stateMachine;
  21. //根据动画文件读取它的AnimationClip对象
  22. AnimationClip newClip = AssetDatabase.LoadAssetAtPath(path, typeof(AnimationClip)) as AnimationClip;
  23. //取出动画名子 添加到state里面
  24. State  state = sm.AddState(newClip.name);
  25. state.SetAnimationClip(newClip,layer);
  26. //把state添加在layer里面
  27. sm.AddAnyStateTransition(state);
  28. }
  29. }

经过这两步操作,Mecanim的状态机编辑变得简化许多。就算依然要编个蜘蛛网出来,也是Hold住的蜘蛛网。由于直接使用Mecanim的功能,所以“边跑边打”“移动施法”这样的依托于动画融合的功能也可以方便的做出来。

Unity Mecanim在大型mmo中的应用的更多相关文章

  1. Spine with Unity Mecanim

    前言 最近这两天刚刚接触Spine,研究了一下Unity Mecanim Animator如何控制Spine,在此分享记录一下,如有不当之处,请留言指出,欢迎讨论. Unity & Spine ...

  2. 【分布式】Zookeeper在大型分布式系统中的应用

    一.前言 上一篇博文讲解了Zookeeper的典型应用场景,在大数据时代,各种分布式系统层出不穷,其中,有很多系统都直接或间接使用了Zookeeper,用来解决诸如配置管理.分布式通知/协调.集群管理 ...

  3. Unity在Android和iOS中如何调用Native API

    本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调 ...

  4. Unity脚本在层级面板中的执行顺序测试3

    断断续续的写了3篇,以后有时间可以做成一个系列了 前面2篇测试了GameObject的顺序,以及Awake和OnEnable的时机: Unity脚本在层级面板中的执行顺序测试1 http://www. ...

  5. Unity脚本在层级面板中的执行顺序测试4-附加整理

    测试4为一些附加内容,后续的各种tips都加在此. 前几篇测试的链接: Unity脚本在层级面板中的执行顺序测试1 http://www.cnblogs.com/hont/p/4298110.html ...

  6. SLAM+语音机器人DIY系列:(二)ROS入门——8.理解roslaunch在大型项目中的作用

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  7. Session的原理,大型网站中Session方面应注意什么?

    一.Session和Cookie的区别Session是在服务器端保持会话数据的一种方法(通常用于pc端网站保持登录状态,手机端通常会使用token方式实现),存储在服务端. Cookie是在客户端保持 ...

  8. Kafka在大型应用中的 20 项最佳实践

    原标题:Kafka如何做到1秒处理1500万条消息? Apache Kafka 是一款流行的分布式数据流平台,它已经广泛地被诸如 New Relic(数据智能平台).Uber.Square(移动支付公 ...

  9. Egret的第三方库制作,以及在大型项目中的应用

    目录: 一 创建第三方库 二 TypeScript库 三 JavaScript库 四 第三方库制作在大型RPG中的实际应用 参考: 第三方库的使用方法 目标: 本文目的是将现有游戏的框架制作成第三方库 ...

随机推荐

  1. EasyDarwin开源流媒体云平台VS调试断点提示“还没有为该文档加载任何符号”的解决办法

    本文转自EasyDarwin开源团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/52063666 近日,我们EasyDarwin ...

  2. vmware安装操作系统

    安装的时候,直接选择“从光盘或者映像安装”就可以了,很方便的.不需要再去从u盘什么的安装了.

  3. Maximum likelihood from incomplete data via the EM algorithm (1977)

    Maximum likelihood from incomplete data via the EM algorithm (1977)  

  4. BZOJ 2069 POI2004 ZAW 堆优化Dijkstra

    题目大意:给定一张无向图.每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路 显然我们须要从点1出发走到某个和点1相邻的点上,然后沿最短路走到还有一个和点1相 ...

  5. iOS10的适配总结(转)

    1.Notification(通知) 自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大改重构,这让开发者也体会到UserN ...

  6. sendevent是使用

    按下: sendevent /dev/input/event4 1 254 1 sendevent /dev/input/event4 0 0 0 松开: sendevent /dev/input/e ...

  7. Ubuntu下codeblocks编译器程序执行对话框内能进行粘贴编辑操作的指令

    如这个:  gnome-terminal  -t $TITLE -x

  8. java多线程-多线程常识

    线程和进程的区别是什么?进程是一个正在运行的软件程序,打开资源管理器可以看到好多正在运行的进程,而线程则是程序中的顺序控制流,只能使用分配给程序的资源和环境.一个进程至少存在一个线程(主线程). 在j ...

  9. powerbuilder

    PowerBuilder美国Sybase公司研制的一种新型.快速开发工具,是客户机/服务器结构下,基于Windows3.x.Windows95和WindowsNT的一个集成化开发工具.它包含一个直观的 ...

  10. 【错误信息】springMVC No mapping found for HTTP request with URI

    出现这个问题的原因是在web.xml中配置错了: