C#開發Unity遊戲教程之遊戲物件的行為邏輯方法

大學霸發表於2015-07-08

C#開發Unity遊戲教程之遊戲物件的行為邏輯方法

遊戲物件的行為邏輯——方法

方法(method),讀者在第1章新建指令碼時就見過了,而且在第2章對指令碼做整體上的介紹時也介紹過,那麼上一章呢,儘管主要內容是變數,但是在章節的最後為了展示遊戲效果,也用到了它。現在看來方法真的是無處不在,並且不可或缺。它甚至都可以影響遊戲物件的行為邏輯!因此本章終於到了不得不介紹它的時候了。

Unity遊戲物件的行為邏輯

遊戲場景中,有些遊戲物件是靜止的,例如,樹木、山峰、石頭等等。而另外一些遊戲物件則是運動的,它們都有自己的行為邏輯。例如,由電腦控制的遊戲物件可能會按照預定的線路行進,如果行進的途中遇到了玩家控制的遊戲物件,還會發起進攻。如圖4-1所示,行為邏輯在遊戲《合金彈頭》中的體現。不管是行進還是進攻,這都屬於遊戲物件的行為邏輯,而決定這一行為邏輯的就是指令碼中的方法。


4-1  《合金彈頭》中各遊戲物件的行為邏輯

Unity指令碼中的方法

前兩章做過兩個遊戲示例,第一個示例中的立方體物件會邊前行邊轉動,第二個示例中的立方體則會在玩家單擊指定的按鈕後,進行移動、旋轉和縮放。在這兩個遊戲中,立方體都表現出了特定的行為邏輯,而決定這些行為邏輯的就是方法。如圖4-2所示的是第一個遊戲示例中的指令碼方法。


4-2  指令碼中決定遊戲物件行為邏輯的方法

上一章的末尾向讀者介紹過語句,那麼再來看指令碼中的方法,它的外在表現形式就是由一條或多條語句組成的。通常情況下,指令碼中宣告的變數是用來儲存資料的,而指令碼中的方法則會對這些資料做一些處理,然後將這些資料應用到遊戲物件行為邏輯的控制中。例如,上一章演示的示例,透過在Inspector檢視裡調節屬性的值,進而影響到立方體物件的縮放大小,如圖4-3所示。


4-3  指令碼中的方法,將屬性中的資料應用到對遊戲物件行為邏輯的控制中

Unity中使用指令碼方法

透過本章前面的介紹,讀者也許已經認識到了方法是有多重要,以至於前面兩章介紹的遊戲示例,都必須在方法的協助下,才實現了最終的效果。方法這麼神奇,讀者現在一定有興趣來了解,那麼本節就來逐步揭開方法的神秘面紗。

Unity中的方法與變數

方法與變數有很多相似的地方。例如,變數與變數名不等價,方法與方法名同樣如此。具體的說明如下:

  • q  方法也是一塊兒特定的儲存空間,只不過方法裡儲存的不是資料,而是程式碼語句;

  • q  方法名也需要遵守C#的命名規則,即名稱必須由字母、數字和下劃線組成,且數字不能作為名稱的首字母,否則就是犯了語法錯誤;

  • q  為了區別方法名與變數名,讀者可以考慮遵守這樣一個約定,即變數名的首字母小寫,方法名的首字母大寫。既然說這是一個約定,讀者當然可以不遵守,也不會犯語法錯誤;

  • q  就像是變數名一樣,方法名也應該取的有意義些。例如,既然方法可以控制遊戲物件的邏輯行為,那麼就可以考慮給控制立方體移動的方法定一個類似於CubeWalking的方法名;

  • q  同樣可以使用publicprivate修飾,只不過方法使用什麼修飾,結果都不會體現在Inspector檢視中,只是會反應在對方法的使用上。即使用public修飾的方法,可以被其它指令碼使用,而使用private修飾,則正好相反。如果省略了對方法的修飾,Unity會認為方式是被private修飾的。

Unity中定義方法

就像是在使用變數前需要宣告變數一樣,使用方法前,需要定義方法。這就像是在告訴Unity:存在這樣一個方法,此方法可以控制遊戲物件做出特定的行為。方法的定義形式如下:

  • 返回值型別  方法名()

  • {

  •          //方法中的語句

  • }

  • q  方法名後的一對括號“( )”是必不可少的;

  • q  被大括號“{ }”括住的語句,就可以看作是儲存於方法中的資料;

  • q  宣告變數時,有些讀者注意到,它的末尾是以分號“;”結尾的,但是對於方法的定義,大括號中的“}”就是結束標識,讀者無需“畫蛇添足”;

  • q  方法可以“返回特定型別的資料”;

例如,前面章節編寫遊戲時,用到的指令碼中的一個方法如下:

  • void Update()

  • {

  •          transform.Translate(new Vector3(xPosition,0,0),Space.World);

  •          transform.Rotate(Vector3.up*yRotation,Space.World);

  • }

對於此方法,Unity會這樣理解:

  • q  這個方法名為Update()

  • q  方法中一共有兩條語句;

  • q  方法返回的資料型別是void。此型別表示方法不會返回任何值。因此,與其說void表示一種型別,還不如說它是一種標誌,即不返回任何型別資料的標誌;

  • q  省略了對方法的修飾,因此Unity會認為它是被private修飾的,因此其它指令碼無法使用這個方法;

Unity中呼叫方法

方法定義好以後,就可以直接使用了。使用方法在指令碼中有個專門術語,就是“呼叫方法”。在指令碼中呼叫方法的方式很簡單,直接使用方法名就可以了,但是千萬不要忘了帶上後面的一對括號“( )”。如下:

  • //方法的定義部分

  • …                                           //省略

  • //呼叫方法

  • AddTwoNumber();

Unity中方法使用示例

理論部分已經寫了很多,讀者應該對方法的概念有印象了才對。那現在就趁熱打鐵,以一個示例來說明方法的定義和呼叫。實現示例的操作步驟如下:

1)在Project檢視裡,新建一個指令碼檔案,命名為MyScript,開啟此指令碼檔案並新增下面的程式碼:

  • 01     using UnityEngine;

  • 02     using System.Collections;

  • 03    

  • 04     public class MyScript : MonoBehaviour

  • 05     {

  • 06              private int number1 = 15;

  • 07              private int number2 = 59;

  • 08              void OnGUI()

  • 09              {

  • 10                       GUILayout.Label ("number1 = " + number1);

  • 11                       GUILayout.Label ("number2 = " + number2);

  • 12                       GUILayout.Label ("number1 + number2 = " + AddTwoNumber ());   //使用方法

  • 13              }

  • 14              int AddTwoNumber()                                                      //定於方法

  • 15              {

  • 16                       return number1 + number2;

  • 17              }

  • 18     }

對於此指令碼的0607行程式碼,讀者一定不陌生。這裡的程式碼完成了變數的宣告和初始化。變數是上一章重點介紹的內容,而本章主要關心14~17行方法的定義部分,以及12行方法的呼叫部分。

  • q  從方法的定義上來看,方法名為AddTwoNumber(),會返回int型別的資料,方法裡只有一行語句,語句的含義是計算兩個整數的和。

  • q  從方法的呼叫上來看,使用方法的方式很簡單,直接書寫AddTwoNumber()就可以了。

2)將指令碼MyScript新增到Main Camera物件上,除此以外遊戲場景中不需要任何其它遊戲物件。直接執行遊戲,在遊戲檢視的左上角會出現3行文字資訊,如圖4-4所示。


4-4  遊戲檢視左上角的文字資訊

3)這只是一個示例,是讓讀者熟悉方法定義和呼叫的示例。所以沒有讓方法控制遊戲物件的行為邏輯,至於方法的遊戲示例,會在本章後續內容講解結束以後給出。

Unity內建的方法

Unity中新建的指令碼檔案,裡面會自動新增一些程式碼,如圖4-5所示。讀者在學習完方法以後,有沒有覺得自動新增的程式碼中,Start()Update()的書寫形式很像方法。沒錯,它們就是方法。只不過它們是Unity內建的方法,他們會被遊戲程式呼叫。


4-5  指令碼中Unity自動新增的程式碼

因為這兩個方法在指令碼中很常用,所以Unity直接在新建的指令碼中新增了它們。那麼,讀者可能要問了,這兩個方法會如何作用於遊戲物件呢?程式碼中使用了註釋(雙斜槓“//”以及後面的部分就是註釋)對這兩個方法進行了簡單的說明:前者在初始化時被呼叫,後者在遊戲執行過程的每一幀被呼叫。如果讀者並不滿足於註釋上的解釋,可以考慮查閱Unity的幫助文件。在第1章中,作者介紹過幫助文件的開啟和檢索方式,忘了的話可以去複習以下。

現以查詢Start()方法的使用說明為例。在幫助文件的檢索框中輸入MonoBehaviour.start,開始查詢。一般情況下會查詢出很多結果,選擇需要的結果,開啟它就可以了。整個過程如圖4-6所示。

在幫助文件中,會首先對這個方法的功能和使用步驟做簡要說明,並在最後給出這個方法的使用示例。

提示:Unity 的指令碼可以使用三種語言編寫,它們是C#JavaScriptBoo,因此幫助文件會給出分別使用這3種語言的使用示例。因為本書講解時使用的語言是C#,所以建議讀者看C#語言編寫的示例。


4-6  使用Unity提供的幫助文件,檢視Start()方法的使用說明

下面使用一個示例來說明,Unity內建方法Start()Update()的使用。示例的操作步驟如下:

1開啟指令碼MyScript,為其新增下面的程式碼:

  • 01     using UnityEngine;

  • 02     using System.Collections;

  • 03    

  • 04     public class MyScript : MonoBehaviour

  • 05     {

  • 06              private int frameCount = 0;

  • 07              void Start()

  • 08              {

  • 09                        Debug.Log ("這是Start()裡輸出的資訊");

  • 10              }

  • 11              void Update()

  • 12              {

  • 13                        frameCount++;

  • 14                       if(frameCount == 100)

  • 15                       {

  • 16                                 Debug.Log ("這是Update()裡輸出的資訊");

  • 17                                 frameCount = 0;

  • 18                       }

  • 19              }

  • 20     }

新新增的程式碼,分別為Start()Update()新增了一條語句(09行)和多條語句(13~18行),實現的功能均是在UnityConsole檢視裡輸出一行文字資訊。讀者可以從輸出的資訊中瞭解到,Start()Update()的呼叫情況。

2執行遊戲,這次觀察的焦點不是Game檢視,而是Console檢視,輸出的文字資訊,如圖4-7所示。


4-7  Console檢視的文字資訊輸出結果

透過Unity提供的幫助文件,讀者應該瞭解到,方法Start()是在遊戲物件初始化的時候呼叫,且是在Update()前被呼叫。因此,Console檢視中首先輸出的是Start()方法裡的文字資訊,而後Update()方法才被呼叫,因此隨後就輸出了Update()方法裡的文字資訊。並且,由於Update()方法在每幀都會被呼叫,因此Update()方法裡的文字資訊會在遊戲執行的過程中,持續輸出。

提示:如果讓Update()方法每幀都輸出資訊的話,Console檢視很快就會被“刷屏”了。為了阻止這種現象的發生,指令碼程式碼只是讓Update()方法每100幀輸出一次文字資訊,但是Update()方法依然在每幀被呼叫。

Unity中的方法的引數

出現在指令碼中的方法,無論是在定義的時候,還是使用的時候,後面都跟著一對括號“( )”,有意義嗎?看起來最多也就是起個快速識別方法的作用吧。既然C#的語法規定方法就應該這麼寫,肯定是有一定道理的。如果是上升到戰略意義的道理,連作者也不是很明白,但是作者知道這對括號裡可以新增“引數”。

Unity中引數的作用

要說明引數的作用,就必須從方法說起。方法可以處理變數中的資料,進而影響遊戲物件的行為邏輯,這是本章前面一直在強調的。但是就前面指令碼中一直在使用的,方法的括號裡沒有引數的情況而言,方法總是在處理特定變數裡的資料。例如,下面是前面一個示例中定義的方法:

  • int AddTwoNumber()        

  • {

  •          return number1 + number2;

  • }

這個方法的括號裡沒有引數,它處理的資料總是變數number1number2裡的資料。既然這只是一個用於求和的方法,沒有必要指定它只計算變數number1number2裡的資料和。如果有其它變數的資料也要求和的話,就只能再定義一個方法了。為方法引入引數就可以很好的解決這類的問題。

對於遊戲的實際意義

開發者定義了一個方法,可以控制一個遊戲物件的邏輯行為。如果其它物件也需要做出與之類似的行為,就沒有必要再定義一個方法了。例如下面的遊戲示例所做的那樣。

1)為遊戲場景新增CubeCylinderDirectional light,這3個遊戲物件。前兩者將作為指令碼方法控制行為邏輯的遊戲物件,最後一個遊戲物件負責遊戲場景的照明。合理設定它們各自的位置,得到的SceneGame檢視,如圖4-8所示。


4-8  SceneGame檢視裡,檢視各物件的相對位置,以及遊戲檢視的效果

2)在Project檢視裡,新建指令碼檔案,命名為MyScript,開啟此指令碼並新增下面的程式碼:

  • 01     using UnityEngine;

  • 02     using System.Collections;

  • 03    

  • 04     public class MyScript : MonoBehaviour

  • 05     {

  • 06              public GameObject myCube;

  • 07              public GameObject myCylinder;

  • 08              void OnGUI()

  • 09              {

  • 10                        //當滑鼠左鍵按下的時候

  • 11                       if(Input.GetMouseButton(0))

  • 12                                 RotateObject (myCube);

  • 13                        //當滑鼠右鍵按下的時候

  • 14                       if(Input.GetMouseButton(1))

  • 15                                 RotateObject (myCylinder);

  • 16              }

  • 17              //改變遊戲物件朝向的方法

  • 18              void RotateObject(GameObject myObject)

  • 19              {

  • 20                       myObject.transform.Rotate(Vector3.right*100,Space.World);

  • 21              }

  • 22     }

  • q  指令碼程式碼的18~21行,是有引數方法的定義部分。從程式碼來看,傳入的引數是一個遊戲物件,而方法中的語句,就是透過修改遊戲物件Transform元件下的Rotation屬性,實現改變遊戲物件朝向的目地的;

  • q  指令碼程式碼的1215行,呼叫了兩次方法RotateObject(),先後傳入的引數也是不一樣的;

3)將指令碼MyScript賦予Main Camera物件,並在後者的Inspector檢視裡,設定My Script元件裡的My CubeMy Cylinder屬性為遊戲場景中的CubeCylinder物件,屬性的設定方法是,直接拖動Hierarchy檢視裡的CubeCylinder物件到對應的屬性框中即可,如圖4-9所示。


4-9  設定My Script元件下的屬性

4)執行遊戲,在Game檢視裡,一直按下滑鼠左鍵,讀者會看到立方體物件在原地滾動。如果一直按下滑鼠右鍵,那麼原地滾動的就成了圓柱體。如果同時按住滑鼠左鍵和右鍵,立方體和圓柱體就會同時滾動了,如圖4-10所示。


4-10  遊戲效果展示圖

5)遊戲中,控制遊戲物件滾動的方法是RotateObject(),它是一個需要傳入引數的方法。正是因為需要傳入引數,所以它才能被用於遊戲場景中,所有遊戲物件滾動的行為邏輯控制中。而不只是單獨的控制一個物件的行為邏輯。

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


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29597077/viewspace-1726613/,如需轉載,請註明出處,否則將追究法律責任。

相關文章