各位朋友,大家好,我是秦元培,歡迎大家關注我的博客,我的博客地址是blog.csdn.net/qinyuanpei。在研究了Unity3D Mecanim動畫系統的重定向特性后,今天我們繼續來探索Mecanim動畫系統很多其它的特性吧。今天博主想和大家分享的是ACT游戲中的三連擊效果的實現,因為Unity3D眼下存在Animation和Animator兩種類型的動畫組件,因此本文將分別講這兩種類型的動畫組件的三連擊效果的實現,當中Animation組件是Unity3.5以下版本號所使用的動畫組件,Animator組件是眼下Unity3D的Mecanim動畫系統所使用的動畫組件。
我們首先來了解三連擊效果的詳細流程,假定角色當前處於Idle狀態,此時玩家假設按下攻擊鍵則進入Attack1狀態,假設在規定的時間內,玩家繼續按下攻擊鍵則進入Attack2狀態,否則返回到Idle狀態;同理,假設角色處於Attack2狀態,假設此時玩家按下攻擊鍵則進入Attack3狀態,否則返回Idle狀態;當Attack3狀態結束后,將返回到Idle狀態,等待玩家觸發下一次攻擊。由此我們能夠歸納出三連擊的狀態變化:
(1)Idle->Attack1->Idle
(2)Idle->Attack1->Attack2->Idle
(3)Idle->Attack1->Attack->Attack3->Idle
通過狀態變化情況我們能夠考慮使用兩種思路來實現三連擊效果。第一種思路是,各狀態動畫相互獨立,通過狀態切換來實現總體的動畫效果。另外一種思路是,美工人員將各狀態動畫以序列形式,程序設計人員依據時間來控制動畫效果。今天我們主要採用第一種方法,目的是領會游戲設計中的有限狀態機思想,將其更好的應用到游戲開發中。好了,以下我們正式開始今天的內容吧!
一、Animator組件篇
Animator組件是Unity3D的Mecanim動畫系統所使用的動畫組件。這個組件通過Animator Controller來實現對動畫的控制。如圖是我們今天項目的主角,一個左手持盾,右手持劍的女戰士。

我們首先來創建一個Animator Controller並將其命名為SwordGirlController,雙擊打開Animator窗體,依照我們對狀態變化情況的討論,我們能夠非常easy地設計出以下的狀態模型:

在這里我們定義一個整型變量ActionID,其默認值為0。當ActionID的值為1時角色由Idle切換到Attack1,當ActionID的值為2時角色由Attack1切換到Attack2,當ActionID為3時角色由Attack2切換到Attack3。全部的指向Idle的連線的切換條件是ActionID的值為0。這樣我們就建立了一個動畫切換的狀態模型。好了,以下我們來編寫腳本實現對動畫的控制:
//基於Mecanim動畫系統的三連擊效果,眼下最大的問題就是玩家在攻擊后無法
//自己主動恢復到Idle狀態,須要運行一次攻擊才干夠回到Idle狀態
using UnityEngine;
using System.Collections;
public class SwordGirlScript : MonoBehaviour {
//Mecanim動畫組件
private Animator mAnimator=null;
//動畫狀態信息
private AnimatorStateInfo mStateInfo;
//定義狀態常量值,前面不要帶層名啊,否則無法推斷動畫狀態
private const string IdleState="Idle";
private const string Attack1State="Attack1";
private const string Attack2State="Attack2";
private const string Attack3State="Attack3";
//定義玩家連擊次數
private int mHitCount=0;
void Start ()
{
//獲取動畫組件
mAnimator=GetComponent<Animator>();
//獲取狀態信息
mStateInfo=mAnimator.GetCurrentAnimatorStateInfo(0);
}
void Update ()
{
//假設玩家處於攻擊狀態,且攻擊已經完畢,則返回到Idle狀態
if(!mStateInfo.IsName(IdleState) && mStateInfo.normalizedTime>1.0F)
{
mAnimator.SetInteger("ActionID",0);
mHitCount=0;
}
//假設按下鼠標左鍵,則開始攻擊
if(Input.GetMouseButton(0))
{
Attack();
}
}
void Attack()
{
//獲取狀態信息
mStateInfo=mAnimator.GetCurrentAnimatorStateInfo(0);
//假設玩家處於Idle狀態且攻擊次數為0,則玩家依照攻擊招式1攻擊,否則依照攻擊招式2攻擊,否則依照攻擊招式3攻擊
if(mStateInfo.IsName(IdleState) && mHitCount==0 && mStateInfo.normalizedTime>0.50F)
{
mAnimator.SetInteger("ActionID",1);
mHitCount=1;
}else if(mStateInfo.IsName(Attack1State) && mHitCount==1 && mStateInfo.normalizedTime>0.65F)
{
mAnimator.SetInteger("ActionID",2);
mHitCount=2;
}else if(mStateInfo.IsName(Attack2State)&& mHitCount==2 && mStateInfo.normalizedTime>0.70F)
{
mAnimator.SetInteger("ActionID",3);
mHitCount=3;
}
}
}
這樣我們就能夠實現ACT游戲中的三連擊效果了,我們一起來看看終於的效果吧!

博主在實際測試的過程中發現角色在運行一次攻擊后無法自己主動恢復到Idle狀態,除非玩家繼續按下攻擊鍵,博主眼下並沒有找到解決的辦法,假設各位朋友知道詳細原因的話,一定要告訴博主啊,哈哈。
二、Animation組件篇
我們知道Mecanim動畫系統是通過狀態機來實現對動畫的控制的,而在3.5版本號曾經的Unity3D所採用的動畫系統呢,依照博主的理解,事實上就是一種無狀態的動畫,我們只能通過動畫片段的名稱來決定播放某一個動畫片段或者在一個確定的時間內進行動畫的切換。因此,假設我們希望使用Animation組件來實現三連擊效果的話,就必須在該組件的基礎上實現一個狀態機的結構。依據開始討論的結果,我們知道整個三連擊過程中有四個狀態Attack1、Attack2、Attack3、Idle,由此我們能夠定義一個動畫狀態的枚舉類型ActionState。接下來我們就能夠依據這個狀態值來切換攻擊動畫,實現三連擊的效果,我們一起來看腳本:
using UnityEngine;
using System.Collections;
public class AttackScripts : MonoBehaviour {
//當前攻擊動畫;
AnimationClip currentClip;
//動畫組件;
Animation mAnimation;
//動畫狀態枚舉
public enum ActionState
{
Attack1,
Attack2,
Attack3,
None
}
//當前動畫狀態;
private ActionState mState = ActionState.None;
//攻擊觸發
void AttackTrigger(){
if (Input.GetMouseButton(0)){
if (mState != ActionState.Attack1 && mState != ActionState.Attack2 && mState != ActionState.Attack3 ) {
mState = ActionState.Attack1;
}else if (mState == ActionState.Attack1 && mState != ActionState.Attack2 && mState != ActionState.Attack3
&& mAnimation[currentClip.name].time > 1.0F){
mState = ActionState.Attack2;
}else if (mState == ActionState.Attack2 && mState != ActionState.Attack1 && mState != ActionState.Attack3
&& mAnimation[currentClip.name].time > 1.0F){
mState = ActionState.Attack2;
}
}
}
//攻擊套路
void Attacks (){
float delayTime =0.0F;
switch (mState){
case ActionState.Attack1:
delayTime = -0.1F;
mAnimation.CrossFade("Attack1", 0.15F);
currentClip = mAnimation["Attack1"].clip;
break;
case ActionState.Attack2:
delayTime = -0.1f;
mAnimation.CrossFade("Attack2", 0.15F);
currentClip = mAnimation["Attack2"].clip;
break;
case ActionState.Attack3:
delayTime = -0.1f;
mAnimation.CrossFade("Attack3", 0.15F);
currentClip = mAnimation["Attack3"].clip;
break;
case ActionState.None:
break;
}
//假設攻擊動畫播放完就切換到Idle狀態
if (mAnimation[currentClip.name].time > (mAnimation[currentClip.name].length +delayTime)){
mState = ActionState.None;
currentClip = mAnimation["Idle"].clip;
}
}
void Awake(){
//獲取動畫組件;
mAnimation = GetComponent<Animation>();
}
void Start () {
if (mAnimation.clip) {
currentClip = mAnimation.clip;
} else {
currentClip = mAnimation["Idle"].clip;
}
}
void Update () {
if (currentClip != null){
AttackTrigger();
Attacks();
}
}
}
這里的連擊效果並沒有設置打斷,即全部的動畫一次性播放完畢。假設我們在Mecanim動畫系統中只保留第三種情形,那么它實現的效果是一樣的,這一點希望大家注意。好了,今天的內容就是這樣了,感謝大家關注我的博客,希望大家能夠喜歡。
每日箴言:無論當下的我們有沒有人愛,我們都要努力做一個可愛的人。不埋怨誰,不嘲笑誰,也不羡慕誰,做自己的夢,走自己的路。

喜歡我的博客請記住我的名字:秦元培,我博客地址是blog.csdn.net/qinyuanpei。
轉載請注明出處,本文作者:秦元培,本文出處:http://blog.csdn.net/qinyuanpei/article/details/38023199
