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. Netty 仿QQ聊天室 (实战二)

    Netty 聊天器(百万级流量实战二):仿QQ客户端 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之15 [博客园 总入口 ] 源码IDEA工程获取链接:Java 聊天室 实战 源码 写在 ...

  2. Raspberry Pi3 ~ 安装 nfs Server

    l  安装必要服务: sudo      apt-get install  portmap sudo  apt-get install  nfs-kernel-server sudo      apt ...

  3. Appnium安装-Mac平台

    Appium的安装-MAC平台   其实Appium的安装方式主要有两种: 1)自己安装配置nodejs的环境,然后通过npm进行appium的安装 2)直接下载官网提供的dmg进行安装,dmg里面已 ...

  4. maven资料

    1.配置settings.xml:http://www.cnblogs.com/jingmoxukong/p/6050172.html?utm_source=gold_browser_extensio ...

  5. div和span、relative和absolute、display和visibility的区别

    一.div和span的区别 div是一个块级元素,可以包含段落,表格等内容,用于放置不同的内容.一般我们在网页通过div来布局定位网页中的每个区块. span是一个内联元素,没有实际意义,它的存在纯粹 ...

  6. JQuery的extend

    jQuery.extend 函数详解 JQuery的extend扩展方法:      Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,在此,我们一起去了解了解 ...

  7. RobotFramework教程使用笔记——Selenium2Library库

    selenium之前已经学习介绍过了,它是一个支持多语言.多平台.多浏览器的web自动化测试框架,在robotframework中也可以导入selenium库来进行web自动化测试.它使用seleni ...

  8. Dubbo与Zookeeper、SpringMVC整合与使用(干货-理论放一遍。。。还未完结!)

    Dubbo跟Zookeeper的简介分享两个不错的链接: Dubbo简介:http://shiyanjun.cn/archives/325.html Zookeeper简介:http://www.op ...

  9. maven项目所遇到的问题解决

    1.在Eclipse中创建Maven的Web项目时出现错误:An internal error occurred during: "Retrieving archetypes:". ...

  10. C++的逐过程和逐语句的区别

    1.逐语句是指在遇到函数调用语句的时候进入到函数内部执行. 2.逐过程是指在遇到函数调用语句时把函数当作一条语句执行.