Unity開啟篇(七) —— Unity動畫簡介 (二)

版本記錄

版本號 時間
V1.0 2019.01.05 星期六

前言

Unity是由Unity Technologies開發的一個讓玩家輕松創建諸如三維視頻游戲、建筑可視化、實時三維動畫等類型互動內容的多平臺的綜合型游戲開發工具,是一個全面整合的專業游戲引擎。Unity類似于Director,Blender game engine, Virtools 或 Torque Game Builder等利用交互的圖型化開發環境為首要方式的軟件。其編輯器運行在Windows 和Mac OS X下,可發布游戲至WindowsMacWiiiPhoneWebGL(需要HTML5)、Windows phone 8和Android平臺。也可以利用Unity web player插件發布網頁游戲,支持Mac和Windows的網頁瀏覽。它的網頁播放器也被Mac 所支持。網頁游戲 坦克英雄和手機游戲王者榮耀都是基于它的開發。
下面我們就一起開啟Unity之旅。感興趣的看下面幾篇文章。
1. Unity開啟篇(一) —— Unity界面及創建第一個簡單的游戲 (一)
2. Unity開啟篇(二) —— Unity界面及創建第一個簡單的游戲 (二)
3. Unity開啟篇(三) —— 一款簡單射擊游戲示例 (一)
4. Unity開啟篇(四) —— 一款簡單射擊游戲示例 (二)
5. Unity開啟篇(五) —— 一款簡單射擊游戲示例 (三)
6. Unity開啟篇(六) —— Unity動畫簡介 (一)

Switching Between Animations – State Machines 101

到目前為止,您已創建了動畫片段(Animation Clips)。 您可以運行它們中的每一個,但無法更改在游戲過程中播放哪一個動畫。 這是狀態機用武之地的地方。

當您創建第一個動畫片段時,Unity已經為小丑創建了一個狀態機。 您可以在Animator View中查看它。 為此,請在層次結構中選擇Clown,然后從菜單中選擇Window \ Animator。 您現在應該看到Game選項卡旁邊的Animator選項卡。

已經有幾種狀態:MoveHorizontallyMoveVerticallyHitEntryExitAnyState。 基本上,每個狀態對應于只要狀態處于活動狀態就正在播放的動畫片段。

您還會看到一個從EntryMoveHorizontally的箭頭。 這意味著MoveHorizontally是默認狀態,即狀態機首次激活時所處的狀態。 它是橙色的。

注意:如果您的屏幕很小并且沒有看到所有狀態,請不要擔心。 只需按住alt鍵并用鼠標左鍵移動鼠標即可在Animator View中導航。

狀態的布局不會影響行為,所以請隨意以適合您的方式安排狀態 - 只需拖動它們即可。

1. Your First Transition

到現在為止還挺好。 現在,您希望小丑在相應動畫結束后立即在MoveHorizontallyMoveVertically之間切換。 從一種狀態切換到另一種狀態稱為轉換。

要創建第一個過渡,請右鍵單擊MoveHorizontally。 從下拉菜單中選擇Make Transition,然后單擊MoveVertically。 這創造了兩個狀態之間的過渡。 對于相反的方向,從MoveVerticallyMoveHorizontally執行相同的操作。

玩游戲:小丑現在從左向右移動,然后向上和向下無限移動。

但是有一些奇怪的事情發生了:小丑在各狀態之間切換時cutting corners。 你從來沒有告訴它這樣做。 這是怎么回事?

要回答這個問題,請在游戲運行時選擇Inspector中的Clown并切換到Animator View。 您將看到處于當前活動狀態的進度條(progress bar )。 仔細觀察并看到,當MoveHorizontallyMoveVertically兩個狀態同時具有進度條時,存在短暫的時間段。 這意味著Unity一次運行兩個狀態,將一個狀態與另一個狀態混合。

混合狀態可能很有用;例如,當你有一個從步行過渡到跑步的角色時,這看起來更自然。 但是也有一些情況你不想混合兩種狀態。 幸運的是,Unity為您提供了允許您控制轉換的設置。

Animator View中,單擊從MoveHorizontallyMoveVertically的過渡箭頭。 在Inspector中,您現在可以看到控制轉換的設置。 通過單擊旁邊的三角形展開設置。 將Exit Time設置為1,將Transition Duration設置為0。對從MoveVerticallyMoveHorizontally的過渡執行相同操作。

運行游戲。 現在,小丑將水平和垂直移動,但不能同時移動。

再看一下過渡設置:

  • 退出時間(Exit Time)確定是否可以在任何時間觸發轉換,或僅在指定的退出時間之后觸發轉換。
  • 退出時間是轉換開始之前的最早時間。它以標準化時間表示。退出時間0.75表示僅在動畫完成75%時才開始轉換。
  • Transition DurationFixed Duration允許您指定轉換所需的時間。如果啟用了Fixed Duration時間,請以秒為單位指定持續時間。否則,請在標準化時間內指定持續時間。
  • Transition Offset控制在轉換到的目標狀態下開始播放的時間的偏移量。例如,值為0.5意味著目標狀態將在其自己的時間軸的50%處開始播放。
  • 中斷源控制(Interrupt Source)是否可以中斷轉換,例如,當觸發另一個轉換時。

有時很難想象這些參數意味著什么。值得慶幸的是,轉換圖(Transition Graph)直接位于檢查器中的轉換設置下方,可以精確地顯示每個動畫的配置方式:

2. Just do it! – The Any State

無論小丑目前處于什么狀態,每當小丑被蛋糕擊中時,你都會想要運行一個命中Hit動畫。你怎么能實現這個目標?

根據您到目前為止所學到的,您可能只需創建兩個到Hit狀態的轉換:一個來自MoveHorizontally狀態,另一個來自MoveVertically狀態。 雖然這會起作用,但它不會擴展。 想象一下,你有一個使用十個狀態的更復雜怪物的游戲。 你可以創建十個轉換,但它會變得混亂,我們希望盡可能簡單。

您可能已經注意到任何狀態(Any State)的綠松石盒子。 它基本上是繪制從所有狀態到單個目標狀態的轉換的簡便方法。 完善!

右鍵單擊AnyState,選擇Make Transition,然后單擊Hit狀態。 現在您的Animator View應如下所示:

Hit動畫完成后,狀態應轉換為MoveHorizontally狀態。

嘗試自己做。 如果你遇到困難,請查看:

右鍵單擊Hit,然后選擇Make Transition并單擊MoveHorizontally以創建過渡。 選擇它。 在Inspector中,將Exit Time設置為1,將Transition Duration設置為0。

3. Control State Switches Using Parameters and Conditions

接下來你需要告訴Unity何時應該在Any StateHit之間進行轉換,因為這不應該自動發生。 你只希望Animator在小丑被擊中時切換到Hit狀態。

為此,您可以使用參數和條件(parameters and conditions)。 參數是您在Animator上指定的變量。 您可以使用它來定義特定轉換發生的條件。

以下是它在實踐中的工作原理:

Animator View的左上角,選擇Parameters選項卡。 單擊+按鈕。 從下拉菜單中,選擇Trigger。 這會創建一個新的觸發器。 命名它hit。 而已! 您現在是第一個參數的自豪擁有者。

CreateParameterCropped

接下來,選擇從任意狀態到Hit的過渡箭頭(transition arrow)。 在“檢查器”中,滾動到Conditions部分。 現在它顯示List is Empty。單擊+按鈕。 這會將命中觸發器添加為條件。

一旦參數hit變為true,現在將觸發轉換。

要手動嘗試,請將動畫視圖拖放到游戲視圖旁邊,以便您可以同時查看兩者。 運行游戲。 在Hierarchy中,選擇Clown。 在Animator視圖中,單擊hit參數后的radio button。 你會聽到飛濺聲,然后小丑重置。 很棒 - 您的動畫控制器按預期工作。

4. Types of Parameters and Combining Conditions

觸發器很有用,但當然可以使用更多參數類型:

  • Float:分數(0.1,0.999,6.31,......)
  • Int:整數(1,5,13,1005,......)
  • 布爾:True or False
  • 觸發器:布爾參數,一旦轉換消耗,就會重置為false

可根據您的要求使用每種類型。 例如,Int可以計算玩家第10次擊中小丑并播放特殊動畫的頻率。

此外,您可以為Animator View的參數列表中的每個參數指定默認值。

條件(Condition)用于決定何時應發生轉換。 您可以在轉換上定義多個條件。 在這種情況下,必須滿足所有條件才能觸發轉換。

你還可以表達,例如,如果小丑被擊中或者時間限制到了,小丑應該轉換到命中狀態。 為此,在Any StateHit狀態之間創建第二個轉換。 在Inspector中,您現在可以看到兩個過渡。 對于每個轉換,您可以單獨定義觸發條件。


Bull’s Eye – Combine Animations and C# Scripts

到目前為止,您已經看到Unity的動畫系統有多強大和靈活,即使沒有一行代碼也是如此。 但是,當然,使用代碼非常有趣,因此從腳本中觸發動畫就是接下來要學習的內容。

1. Trigger an Animation From Code

在對碰撞做出反應之前,您需要能夠檢測到它。 在層次結構中展開小丑并選擇其子皮膚(Skin)。 在Inspector中,單擊Add Component并選擇Physics \ Mesh Collider。 在新的Mesh Collider組件中,勾選Convex

你現在可以看到小丑皮膚周圍的薄綠色邊框。 當然,形狀并不完全適合小丑,但它足夠接近。

試試看。 運行游戲 - 蛋糕(因為它也有一個Collider)不再飛過小丑。

要在代碼中檢測此沖突,請在“檢查器”中選擇Skin。 單擊添加組件Add Component,然后選擇新腳本New Script。 將腳本命名為CollisionBehavior,將Language設置為C Sharp,然后按Create and Add

當另一個Collider碰到小丑的Mesh Collider時,它會觸發OnCollisionEnter。 通過雙擊項目瀏覽器中的文件,在MonoDevelop中打開CollisionBehavior

在行void Start()上面的CollisionBehavior中添加以下代碼:

// 1
public bool collided;

//2
void OnCollisionEnter(Collision collision) {
  if (!collided) {
    collided = true;
    // 3
    GameObject clown = gameObject.transform.parent.gameObject;
    Animator clownAnimator = clown.GetComponent<Animator> ();
    // 4
    clownAnimator.SetTrigger ("hit");
  }
}

下面進行詳細分解:

  • 1) 創建一個bool變量,記住小丑是否已經碰撞過。
  • 2) 如果小丑還沒有碰撞,則僅觸發動畫。 下一行設置collidedtrue,以確保您只觸發一次Hit動畫。
  • 3) 獲取Clown GameObject,它是當前gameObject的父級,然后使用GetComponent檢索Animator
  • 4) 在clownAnimator上調用SetTrigger。 這使得動畫師進入了Hit狀態。 對于其他參數類型,您可以使用SetFloatSetIntSetBoolResetTrigger

運行游戲,進行投擲。 當你設法擊中小丑時,它會發出嘩然的聲音!

2. State Machine Behaviors: React to State Changes in Your Scripts

狀態機行為(State Machine Behaviors)允許您編寫依賴于狀態的行為。 例如,只要它處于Hit狀態,你就可以使小丑縮小。 試試看:

Unity中,轉到Animator View并選擇Hit狀態。 在Inspector中,單擊Add Behavior。 選擇New Script,將其命名為ClownHitBehavior,然后按Create and Add

雙擊ClownHitBehavior打開它。 你可能會注意到Unity已經添加了一些被注釋掉的方法。 不要擔心它們 - 你會很快了解它們的作用。 而是專注于縮放小丑!

為此,請在ClownHitBehavior中添加startTime變量。

float startTime;

此變量將存儲進入Hit狀態的時間。 您可以使用它來控制動畫的速度,具體取決于實際時間而不是幀速率。 這確保了無論游戲運行速度有多快,小丑都會以相同的速度收縮。

接下來,查找(注釋掉)OnStateEnter方法。 在此方法中,您設置startTime的值。 替換為:

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
  startTime = Time.time;
}

當狀態機進入命中狀態時調用OnStateEnter。 使用Time.time,您可以檢索自游戲開始以來的秒數。 雖然創造一個時鐘并不是那么好,但這對于縮小你的小丑還是很有效的。

接下來,查找OnStateUpdate方法并將其替換為以下代碼:

override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
  GameObject clown = animator.gameObject;
  clown.transform.localScale *= Mathf.Lerp (1, 0, Time.time - startTime);
}

Hit狀態處于活動狀態時,每個幀都會調用OnStateUpdate。在每一幀中,您都可以調整小丑的大小。

為此,您首先需要找到Clown GameObject。當腳本在Animator組件上運行時,您不能像以前那樣通過gameObject簡單地訪問它。相反,請為該gameObject詢問該方法的animator變量,然后將其存儲在clown變量中。

接下來,使用Mathf.Lerp更改Clown GameObject的比例。該方法在兩個數值之間線性插值linearly interpolates

例如,屏幕上有兩個不同的點。一個是y位于左邊0,另一個是y位于右邊的20處。傳入.50Math.Lerp將返回中間的一個點。

使用三個參數調用Math.Lerp:它們之間插入的兩個值,在本例中為10,以及自Hit動畫開始以來的秒數。 Lerp然后計算得到的比例。例如,在0秒時它將返回1,在1秒時它將返回0,在0.75秒時它將返回0.25。

在小丑打擊和投擲蛋糕直到你hit命中 - 小丑縮小,再也不會再出現。一場短暫的游戲!

注意:如果您想知道狀態機行為中的其他方法是什么:

  • OnStateEnter:在正在播放的狀態的第一幀上調用OnStateEnter
  • OnStateUpdate:在每個幀上更新MonoBehaviors之后調用OnStateUpdate,同時播放它所附加的行為的狀態。
  • OnStateExit:在轉換到另一個狀態的最后一幀上調用OnStateExit
  • OnStateMove:只要狀態正在播放,就會在每個幀的MonoBehaviors上調用OnStateMove而不是OnAnimatorMove
  • OnStateIK:Unity計算人形角色的反向運動學 Inverse Kinematics后調用OnStateIK - 例如,允許它抓取項目。

3. Animation Events: Trigger Code From Your Animation

是時候讓小丑再次適應值班。 一個很好的方法是通過Animation Events,它允許您在動畫片段運行時從游戲對象的腳本中調用函數。

首先,您需要一個腳本,其方法可以重置小丑的大小。 在層次結構中選擇小丑。 在“檢查器”中,滾動到底部,然后單擊Add Component。 選擇New Script并將腳本ResetClown命名為C Sharp。 點擊Create and Add

MonoDevelop中打開ResetClown腳本并添加以下代碼:

void ResetClownOnHit () {
  gameObject.transform.localScale = Vector3.one;
  gameObject.GetComponentInChildren<CollisionBehavior> ().collided = false;
}

在此方法中,將小丑的localScale設置為1以恢復其原始大小。 然后使用GetComponentInChildren()引用Skin上的CollisionBehavior并確保其碰撞變量設置為false。 如果你省略這一步,你的小丑仍然會移動,但不會再對碰撞作出反應。

現在您需要創建一個調用此方法的Animation Event。 在“層次結構”中選擇“小丑”時切換到Animation View,然后選擇Hit動畫片段。 在時間線中將播放頭設置為1:30。 如果您的時間線在1:00以后不可見,請使用滾輪將其縮小。 然后單擊Add Event按鈕。

雙擊剛剛創建的動畫事件的marker

在對話框窗口中,選擇ResetClownOnHit()

這將創建一個動畫事件,在1:30調用ResetClownOnHit()方法。

運行游戲。 現在小丑縮小了,然后重新開始并再次開始移動,準備再被蛋糕破壞了!

在本教程中,您可以看到Unity動畫系統的可能性。 但是要知道你還有很多需要學習,下面是一些閱讀建議:

后記

本篇主要講述了Unity動畫簡介,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容