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. iphone开发的技巧

    一,改动状态栏: 1.增加[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];但此方法仅仅是不显示状态条,状态 ...

  2. [听听音乐]X-Ray Dog

    X-Ray Dog是一个专门为好莱坞电影预告配乐的音乐工作室. https://music.163.com/#/artist?id=105618 有空的时候听听.

  3. LINUX上一个命令计算PI

    Linux上一个命令计算PI – 笑遍世界 http://smilejay.com/2017/11/calculate-pi-with-linux-command/ [root@d1 goEcho]# ...

  4. POJ2559 Largest Rectangle in a Histogram —— 单调栈

    题目链接:http://poj.org/problem?id=2559 Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Lim ...

  5. 自动化测试框架selenium+java+TestNG——读取csv文件

    读取csv文件可以直接读取,也可以使用javacsv.jar,后者比较简单,这个也可以变相认为是对表格的处理,我们可以在表格中做好数据,存储成csv格式的文件,后续对xlsx表格的操作抽个时间再记录下 ...

  6. BZOJ_3680_吊打XXX_模拟退火

    BZOJ_3680_吊打XXX_模拟退火 Description gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty.gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了.蒟蒻们将 n个g ...

  7. centos7使用ceph-deploy部署ceph

    准备阶段 准备yum源 删除默认的源,国外的比较慢 yum clean all rm -rf /etc/yum.repos.d/*.repo 下载阿里云的base源 wget -O /etc/yum. ...

  8. 级联MobileNet-V2实现CelebA人脸关键点检测(转)

    https://blog.csdn.net/u011995719/article/details/79435615

  9. 51nod1228

    伯努利数 这个是答案 其中的b是伯努利数,可以n^2预处理 伯努利数n^2递推 #include<bits/stdc++.h> using namespace std; typedef l ...

  10. 关于try catch finally的执行顺序解释

    偶然遇到了被问到finally的执行问题,忽然发现一直用的都是try catch 没有用过finally的情况,所以目前总结一下. 先抛出结论: 1.try内部正常执行try的内部逻辑,异常则执行ca ...