Unity3D 4.x 使用Mecanim实现动画控制

unity3d 4.x 版本之后提供了一种新的动画机制Mecanim,虽然目前还支持之前的Animation,但看到unity3d 4.3 预览版里Sprite的动画也是基于Animator的,可知Mecanim将会是以后动画播放的趋势!


  Mecanim是一种基于状态机的结构,不同的状态表示一个动作(或者多个动作融合,或者一个子状态机),状态之间使用一种称为Transition的组件关联,Transition中可以设定一些条件,当在Transition“源状态”下,满足其条件之后,将自动跳转到Transition“目的状态”!(具体用法请参照Unity3d手册Mecanim)在一些ARPG的游戏中,比如 端游的DNF和闯关类的街机游戏,连续按攻击键都会触发一套组合攻击,在这个过程中敌人一般是硬直状态的,而且组合攻击的最后一下一般是重击,这样做既增加了连击带来的爽快感,又促使玩家在攻击时采取一定的攻击策略!


  Mecanim的状态机设计就很方便的使开发者实现了这一效果!


   1.动画状态机

  这里只用4个动作描述,待命状态(Idle),攻击1状态(AtkSlice),攻击2状态(AtkStab),攻击3状态(AtkCleave),3个攻击状态分别表示连续按下“普通攻击键”时触发的状态,是有先后顺序关系的,即如果在待命状态下按下“攻击键”,则进入攻击1状态;如果在攻击1状态下继续按下“攻击键”,则进入攻击2状态,如果不按下“攻击键”,则回到待命状态;攻击2状态到攻击3状态同理;攻击3状态认为是重击,即连击结束,回到待命状态!

  状态图如下


我希望能以最少的代码和设置完成这个功能,所以只添加了一个状态机参数 ActionCMD,假设 ActionCMD = 1 为进入攻击状态参数

(1)在任意3种攻击状态下,不再继续按下“攻击键”,则回到待命状态,即上图 3条白色Transition(2)在待命,攻击1,攻击2状态下,继续按下“攻击键”,则跳转到连击状态(即下一个攻击状态),即上图3条蓝色Transition
2.代码实现(1)状态机设置完成之后,要做的就是在代码中完成对当前状态的判断,以及对状态参数的设置,用以完成动画状态机的切换!

[JavaScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
// 使用字符串变量保存当前状态,避免多处引用写错 
     private static readonly string IdleState = "BaseLayer.Idle"
     private static readonly string AtkSliceState = "BaseLayer.AtkSlice"
     private static readonly string AtkStabState = "BaseLayer.AtkStab"
     private static readonly string AtkCleave = "BaseLayer.AtkCleave"
     // 动画状态机参数Key 
     private static readonly string ActionCMD = "ActionCMD"
   
     private Animator animator = null
     // 当前连击数(即 玩家按下攻击键的次数) 
     private int curComboCount = 0;


(2)在Start() 中获取Animator组件引用
(3)在Update() 中根据当前状态和输入参数促使状态切换
[JavaScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Update() 
    
         AnimatorStateInfo stateInfo = this .animator.GetCurrentAnimatorStateInfo(0); 
         if (!stateInfo.IsName(IdleState)) 
        
             // 每次设置完参数之后,都应该在下一帧开始时将参数设置清空,避免连续切换 
             this .animator.SetInteger(ActionCMD, 0); 
        
   
         if (stateInfo.IsName(AtkSliceState) && (stateInfo.normalizedTime > 0.6f) && ( this .curComboCount == 2)) 
        
             // 当在攻击1状态下,并且当前状态运行了0.6正交化时间(即动作时长的60%),并且用户在攻击1状态下又按下了“攻击键” 
             this .animator.SetInteger(ActionCMD, 1); 
        
         if (stateInfo.IsName(AtkStabState) && (stateInfo.normalizedTime > 0.8f) && ( this .curComboCount == 3)) 
        
             // 挡在攻击2状态下(同理攻击1状态) 
             this .animator.SetInteger(ActionCMD, 1); 
        
   
         if (Input.GetKeyUp(KeyCode.J)) 
        
             // 监听用户输入(假设J键为攻击键) 
             Attack(); 
        
     }


[JavaScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
void Attack() 
    
         AnimatorStateInfo stateInfo = this .animator.GetCurrentAnimatorStateInfo(0); 
         if (stateInfo.IsName(IdleState)) 
        
             // 在待命状态下,按下攻击键,进入攻击1状态,并记录连击数为1 
             this .animator.SetInteger(ActionCMD, 1); 
             this .curComboCount = 1; 
        
         else if (stateInfo.IsName(AtkSliceState)) 
        
             // 在攻击1状态下,按下攻击键,记录连击数为2(切换状态在Update()中) 
             this .curComboCount = 2; 
        
         else if (stateInfo.IsName(AtkStabState)) 
        
             // 在攻击2状态下,按下攻击键,记录连击数为3(切换状态在Update()中) 
             this .curComboCount = 3; 
        
     }



这里需要注意的是,在Update() 中使用的0.6和0.8 应该分别小于当前状态跳转到待命状态的参数Exit Time(这个时间也是正交化的)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值