Unity 2D遊戲開發教程之遊戲中精靈的跳躍狀態

Unity 2D遊戲開發教程之遊戲中精靈的跳躍狀態

精靈的跳躍狀態

爲了讓遊戲中的精靈有更大的活動範圍,上一節爲遊戲場景添加了多個地面,因而精靈能夠從高的地面移動到低的地面處,如圖2-14所示。可是卻沒法從低的地面移動到高的地面,由於當前的遊戲精靈只能左右移動,即leftright。爲了解決這個問題,本節就來爲精靈添加跳躍狀態。ide

2-14  精靈從一個地面移動到另外一個地面函數

1若是要爲精靈添加跳躍狀態,即jump,就不得再也不引入其它狀態:動畫

  • q   landing:用於表示精靈接觸到地面的這種狀態。爲了阻止精靈在跳躍到空中的時候再次跳躍,就須要在精靈作跳躍動做以前,確認其接觸到了地面。ui

提示:有些遊戲容許精靈在空中的時候再跳躍一次,也就是所謂的二級跳。例如,《每天酷跑》中,精靈就須要有二級跳的能力,由於有些場景光是跳躍一次沒法跳過懸崖,或者吃到金幣,如圖2-15所示。spa

2-15  《每天酷跑》中,須要連續跳躍來越過斷崖的精靈orm

  • q   falling:用於表示精靈在空中的狀態,處於此種狀態下的精靈只可能過渡到landingkill狀態,也就是說精靈在空中的時候,沒法產生其它動做行爲,如leftright對象

2爲腳本PlayerStateController中定義的動畫狀態枚舉類型添加3種新的狀態:jumplandingfalling,而且設置當玩家按下鍵盤上的空格鍵時,精靈會進入跳躍狀態。腳本PlayerStateController中的部分代碼以下:教程

  • 01     using UnityEngine;遊戲

  • 02     using System.Collections;ip

  • 03    

  • 04     public class PlayerStateController : MonoBehaviour

  • 05     {

  • 06              //定義遊戲人物的各類狀態

  • 07              public enum playerStates

  • 08              {

  • 09                       …                                                             //省略

  • 10                       jump,                                                       //表示跳躍

  • 11                       landing,                                                   //表示落地

  • 12                       falling,                                                     //表示降落過程

  • 13              }

  • 14              …                                                                       //省略

  • 15              void LateUpdate ()

  • 16              {

  • 17                       …                                                             //省略

  • 18                       //當玩家按下鍵盤上的空格鍵時,進入跳躍狀態

  • 19                       float jump = Input.GetAxis("Jump");

  • 20                       if(jump > 0.0f)

  • 21                       {

  • 22                                 if(onStateChange != null)

  • 23                                          onStateChange(PlayerStateController.playerStates.jump);

  • 24                       }

  • 25              }

  • 26     }

3Hierarchy視圖裏,新建一個Empty對象,命名爲SceneryToggler,並拖動它到Player對象下,使其成爲Player對象的子對象。爲其添加Box Collider 2D組件,並在Inspector視圖裏,設置此組件的屬性,如圖2-16所示。

  • q   選中Is Trigger複選框;

  • q   Sizex:1,y:2

  • q   Centerx:0,y:1

2-16  SceneryToggler對象上,組件屬性的設置

如此這般設置,至關於爲Player對象添加了一個Collider檢測框,如圖2-17所示,能夠看出除了精靈自身的Polygon Collider 2D的線框外,外層還包裹了矩形的線框。它在後面將用於檢測精靈與場景中其它對象的碰撞。

2-17  精靈對象外層包裹的矩形線框

讀者此時心中必定在疑惑,既然精靈自己就有Collider,爲何還要添加一個Collider呢?答案是,精靈是有實體的,所以即便其它對象與精靈發生了接觸,它們也不會「交叉」,所以就永遠不會觸發咱們指望的landing狀態。可是對於Empty對象而言,就沒有這種擔憂了,由於它根本沒有實體,所以會與其它對象發生「交叉」,而後觸發landing狀態。

4Unity裏,單擊Edit|Project Settings|Tags and Layers命令,打開Tag&Layers對話框,爲Tags屬性添加兩個元素:PlatformDeathTrigger,如圖2-18所示。

2-18  Tag&Layers對話框裏,爲Tags屬性添加兩個元素

而後修改場景裏地面對象的Tag屬性爲PlatformDeath Trigger對象的Tag屬性爲DeathTrigger

5Project視圖裏的Scripts文件夾下,新建一個C#腳本,命名爲PlayerColliderListener,爲此腳本添加下面的代碼:

  • 01     using UnityEngine;

  • 02     using System.Collections;

  • 03    

  • 04     public class PlayerColliderListener : MonoBehaviour

  • 05     {

  • 06              public PlayerStateListener targetStateListener = null;                          //表示精靈對象

  • 07         //進入碰撞檢測區域時,調用此函數

  • 08              void OnTriggerEnter2D( Collider2D collidedObject )

  • 09         {

  • 10                       switch(collidedObject.tag)

  • 11             {

  • 12                                 //當精靈落到地面上時,觸發landing動畫狀態

  • 13                                 case "Platform":

  • 14                                         targetStateListener.onStateChange(PlayerStateController.playerStates.landing);

  • 15                                 break;

  • 16                       }

  • 17              }

  • 18              //離開碰撞檢測區域時,調用此函數

  • 19              void OnTriggerExit2D( Collider2D collidedObject)

  • 20              {

  • 21                       switch(collidedObject.tag)

  • 22                       {

  • 23                                 //當精靈離開地面是,觸發falling動畫狀態

  • 24                                 case "Platform":

  • 25                                         targetStateListener.onStateChange(PlayerStateController.playerStates.falling);

  • 26                                 break;

  • 27                                 //當精靈離開的是Death Trigger對象,則觸發kill動畫狀態

  • 28                                 case "DeathTrigger":

  • 29                                         targetStateListener.onStateChange(PlayerStateController.playerStates.kill);

  • 30                                 break;      

  • 31                       }        

  • 32              }

  • 33     }

將此腳本賦予Player對象的子對象SceneryToggler,選中後者,而後在Inspector視圖裏設置此腳本組件的Target State Listener屬性爲Player對象,如圖2-19所示。

2-19  設置腳本組件裏的屬性

對於此腳本,有如下幾點須要說明:

  • q   腳本08行定義的OnTriggerEnter2D(),說明當與SceneryToggler對象發生碰撞的對象的Tag屬性是Platform的時候(精靈與地面接觸),精靈就會進入landing狀態;

  • q   腳本19行定義的OnTriggerExit2D(),說明當離開SceneryToggler對象檢測範圍的對象的Tag屬性是Platform的時候(精靈離開地面),精靈就會進入falling狀態;Tag屬性爲DeathTrigger的時候(精靈離開場景中的Death Trigger對象),精靈就會進入kill狀態;

提示:若是讀者再回頭細細的查看精靈的死亡邏輯的話,就會發現精靈的死亡只是表象!本質上是精靈在一瞬間轉移到了重生點所在的位置。正是由於遊戲中是如此實現精靈死亡邏輯的,因此才須要檢測碰撞對象的Tag屬性是否爲Death Trigger

6)爲腳本PlayerStateListener添加對jumplandingfalling這些狀態的處理,以下:

  • 01     using UnityEngine;

  • 02     using System.Collections;

  • 03    

  • 04     [RequireComponent(typeof(Animator))]

  • 05     public class PlayerStateListener : MonoBehaviour

  • 06     {

  • 07              public float playerWalkSpeed = 3f;                               //表示精靈移動的速度

  • 08              public GameObject playerRespawnPoint = null;                 //表示重生的點

  • 09              public float playerJumpForceVertical = 300f;          //表示跳躍時,水平方向上,力的大小

  • 10              public float playerJumpForceHorizontal = 200f;     //表示跳躍時,垂直方向上,力的大小

  • 11              private bool playerHasLanded = true;                       //表示精靈是否落地

  • 12              …                                                                                         //省略

  • 13              //當角色的狀態發生改變的時候,調用此函數

  • 14              public void onStateChange(PlayerStateController.playerStates newState)

  • 15              {

  • 16                       //若是狀態沒有發生變化,則無需改變狀態

  • 17                       if(newState == currentState)

  • 18                                 return;

  • 19                       //判斷精靈可否由當前的動畫狀態,直接轉換爲另外一個動畫狀態

  • 20                       if(!checkForValidStatePair(newState))

  • 21                                 return;

  • 22                       //經過修改ParameterWalking的值,修改精靈當前的狀態

  • 23                       switch(newState)

  • 24                       {

  • 25                       …                                                             //省略

  • 26                       case PlayerStateController.playerStates.jump:

  • 27                                 if(playerHasLanded)

  • 28                                 {

  • 29                                          //肯定精靈的跳躍方向

  • 30                                          float jumpDirection = 0.0f;

  • 31                                          if(currentState == PlayerStateController.playerStates.left)

  • 32                                                   jumpDirection = -1.0f;

  • 33                                          else if(currentState == PlayerStateController.playerStates.right)

  • 34                                                   jumpDirection = 1.0f;

  • 35                                          else

  • 36                                                   jumpDirection = 0.0f;

  • 37                                          //給精靈施加一個特定方向的力

  • 38                                          rigidbody2D.AddForce(new Vector2(jumpDirection * playerJumpForceHorizontal,

  • 39                                                                      playerJumpForceVertical));

  • 40                                          playerHasLanded = false;

  • 41                                 }

  • 42                                 break;

  • 43                       case PlayerStateController.playerStates.landing:

  • 44                                 playerHasLanded = true;

  • 45                                 break;

  • 46                       }

  • 47                       //記錄角色當前的狀態

  • 48                       currentState = newState;

  • 49              }   

  • 50              //用於確認當前的動畫狀態可否直接轉換爲另外一動畫狀態的函數

  • 51              bool checkForValidStatePair(PlayerStateController.playerStates newState)

  • 52              {

  • 53                       bool returnVal = false;

  • 54                       //比較兩種動畫狀態

  • 55                       switch(currentState)

  • 56                       {

  • 57                       …                                                    //省略

  • 58                       case PlayerStateController.playerStates.jump:

  • 59                                 if(    newState == PlayerStateController.playerStates.landing

  • 60                                          || newState == PlayerStateController.playerStates.kill

  • 61                                          )

  • 62                                          returnVal = true;

  • 63                                 else

  • 64                                          returnVal = false;

  • 65                                 break;

  • 66                       case PlayerStateController.playerStates.landing:

  • 67                                 if(    newState == PlayerStateController.playerStates.left

  • 68                                          || newState == PlayerStateController.playerStates.right

  • 69                                          || newState == PlayerStateController.playerStates.idle

  • 70                                          )

  • 71                                          returnVal = true;

  • 72                                 else

  • 73                                          returnVal = false;

  • 74                                 break;             

  • 75                       case PlayerStateController.playerStates.falling:   

  • 76                                 if(      newState == PlayerStateController.playerStates.landing

  • 77                                          || newState == PlayerStateController.playerStates.kill

  • 78                                          )

  • 79                                          returnVal = true;

  • 80                                 else

  • 81                                          returnVal = false;

  • 82                                 break;             

  • 83                       }         

  • 84                       return returnVal;

  • 85              }

  • 86              …                                                             //省略

  • 87     }

修改後的腳本,在腳本組件裏就會多出兩個屬性,分別用於決定精靈跳躍時水平和垂直方向受到的力,如圖2-20所示。

2-20  修改後的腳本組件

對於此腳本里新加入的代碼,有如下幾點須要說明:

  • q   腳本09~11行,定義了3個變量:playerJumpForceVerticalplayerJumpForceHorizontalplayerHasLanded,用於輔助新加入狀態的邏輯實現;

  • q   腳本14行,onStateChange()裏添加的代碼說明,精靈只有在落地的時候才能繼續跳躍,並且腳本會依據精靈當前的運動朝向,來決定是朝左跳仍是朝右跳,具體的方法是,給精靈的剛體施加一個力,精靈將在此力的做用下產生相似於跳躍的行爲。

  • q   腳本51行,checkForValidStatePair()裏添加的代碼說明,jump狀態只能轉換爲landingkill狀態;landing狀態只能轉換爲leftrightidle狀態;falling狀態只能轉換爲landingkill狀態;

7運行遊戲,按下空格的時候,精靈就會進入jump狀態了。當精靈處於idle狀態時,精靈會原地起跳;處於left狀態時,會朝左跳,同理right狀態;最終,精靈能夠在多個地面間上竄下跳,如圖2-21所示。

2-21  精靈的跳躍狀態(原地起跳、左跳和右跳)

提示:當精靈與Death Trigger對象接觸,並進入死亡狀態時,Unity裏的Console視圖裏會彈出一條警告信息:hitDeathTrigger has no receiver!,如圖2-22所示。

2-22  Console視圖裏彈出的警告信息

這是因爲腳本PlayerColliderListener裏包含了方法OnTriggerExit2D(),代碼以下:

  • 01              //離開碰撞檢測區域時,調用此函數

  • 02              void OnTriggerExit2D( Collider2D collidedObject)

  • 03              {

  • 04                       switch(collidedObject.tag)

  • 05                       {

  • 06                                 //當精靈離開地面是,觸發falling動畫狀態

  • 07                                 case "Platform":

  • 08                                         targetStateListener.onStateChange(PlayerStateController.playerStates.falling);

  • 09                                 break;

  • 10                                 //當精靈離開的是Death Trigger對象,則觸發kill動畫狀態

  • 11                                 case "DeathTrigger":

  • 12                                          targetStateListener.onStateChange(PlayerStateController.playerStates.kill);

  • 13                                 break;

  • 14                       }

  • 15              }

代碼中加粗的部分直接激活了精靈的kill狀態,所以再也不須要hitDeathTrigger()方法去激活這個狀態。所以,讀者能夠作兩步操做,來解決Console視圖裏提示的警告信息。首先,移除Death Trigger對象上的Death Trigger Script組件,而後,移除腳本PlayerStateListener裏定義的hitDeathTrigger()方法:

  • 01              public void hitDeathTrigger()

  • 02              {

  • 03                       onStateChange(PlayerStateController.playerStates.kill);

  • 04              }

本文選自:Unity 2D遊戲開發快速入門大學霸內部資料,轉載請註明出處,尊重技術尊重IT人!

相關文章
相關標籤/搜索