方法(method),讀者在第1章新建腳本時就見過了,並且在第2章對腳本作總體上的介紹時也介紹過,那麼上一章呢,儘管主要內容是變量,可是在章節的最後爲了展現遊戲效果,也用到了它。如今看來方法真的是無處不在,而且不可或缺。它甚至均可以影響遊戲對象的行爲邏輯!所以本章終於到了不起不介紹它的時候了。學習
遊戲場景中,有些遊戲對象是靜止的,例如,樹木、山峯、石頭等等。而另一些遊戲對象則是運動的,它們都有本身的行爲邏輯。例如,由電腦控制的遊戲對象可能會按照預約的線路行進,若是行進的途中遇到了玩家控制的遊戲對象,還會發起進攻。如圖4-1所示,行爲邏輯在遊戲《合金彈頭》中的體現。不論是行進仍是進攻,這都屬於遊戲對象的行爲邏輯,而決定這一行爲邏輯的就是腳本中的方法。spa
圖4-1 《合金彈頭》中各遊戲對象的行爲邏輯orm
前兩章作過兩個遊戲示例,第一個示例中的立方體對象會邊前行邊轉動,第二個示例中的立方體則會在玩家單擊指定的按鈕後,進行移動、旋轉和縮放。在這兩個遊戲中,立方體都表現出了特定的行爲邏輯,而決定這些行爲邏輯的就是方法。如圖4-2所示的是第一個遊戲示例中的腳本方法。對象
圖4-2 腳本中決定遊戲對象行爲邏輯的方法教程
上一章的末尾向讀者介紹過語句,那麼再來看腳本中的方法,它的外在表現形式就是由一條或多條語句組成的。一般狀況下,腳本中聲明的變量是用來存儲數據的,而腳本中的方法則會對這些數據作一些處理,而後將這些數據應用到遊戲對象行爲邏輯的控制中。例如,上一章演示的示例,經過在Inspector視圖裏調節屬性的值,進而影響到立方體對象的縮放大小,如圖4-3所示。遊戲
圖4-3 腳本中的方法,將屬性中的數據應用到對遊戲對象行爲邏輯的控制中ip
經過本章前面的介紹,讀者也許已經認識到了方法是有多重要,以致於前面兩章介紹的遊戲示例,都必須在方法的協助下,才實現了最終的效果。方法這麼神奇,讀者如今必定有興趣來了解,那麼本節就來逐步揭開方法的神祕面紗。遊戲開發
方法與變量有不少類似的地方。例如,變量與變量名不等價,方法與方法名一樣如此。具體的說明以下:開發
q 方法也是一起特定的存儲空間,只不過方法裏存儲的不是數據,而是代碼語句;文檔
q 方法名也須要遵照C#的命名規則,即名稱必須由字母、數字和下劃線組成,且數字不能做爲名稱的首字母,不然就是犯了語法錯誤;
q 爲了區別方法名與變量名,讀者能夠考慮遵照這樣一個約定,即變量名的首字母小寫,方法名的首字母大寫。既然說這是一個約定,讀者固然能夠不遵照,也不會犯語法錯誤;
q 就像是變量名同樣,方法名也應該取的有意義些。例如,既然方法能夠控制遊戲對象的邏輯行爲,那麼就能夠考慮給控制立方體移動的方法定一個相似於CubeWalking的方法名;
q 一樣可使用public和private修飾,只不過方法使用什麼修飾,結果都不會體如今Inspector視圖中,只是會反應在對方法的使用上。即便用public修飾的方法,能夠被其它腳本使用,而使用private修飾,則正好相反。若是省略了對方法的修飾,Unity會認爲方式是被private修飾的。
就像是在使用變量前須要聲明變量同樣,使用方法前,須要定義方法。這就像是在告訴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修飾的,所以其它腳本沒法使用這個方法;
方法定義好之後,就能夠直接使用了。使用方法在腳本中有個專門術語,就是「調用方法」。在腳本中調用方法的方式很簡單,直接使用方法名就能夠了,可是千萬不要忘了帶上後面的一對括號「( )」。以下:
//方法的定義部分
… //省略
//調用方法
AddTwoNumber();
理論部分已經寫了不少,讀者應該對方法的概念有印象了纔對。那如今就趁熱打鐵,以一個示例來講明方法的定義和調用。實現示例的操做步驟以下:
(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 }
對於此腳本的06、07行代碼,讀者必定不陌生。這裏的代碼完成了變量的聲明和初始化。變量是上一章重點介紹的內容,而本章主要關心14~17行方法的定義部分,以及12行方法的調用部分。
q 從方法的定義上來看,方法名爲AddTwoNumber(),會返回int類型的數據,方法裏只有一行語句,語句的含義是計算兩個整數的和。
q 從方法的調用上來看,使用方法的方式很簡單,直接書寫AddTwoNumber()就能夠了。
(2)將腳本MyScript添加到Main Camera對象上,除此之外遊戲場景中不須要任何其它遊戲對象。直接運行遊戲,在遊戲視圖的左上角會出現3行文本信息,如圖4-4所示。
圖4-4 遊戲視圖左上角的文本信息
(3)這只是一個示例,是讓讀者熟悉方法定義和調用的示例。因此沒有讓方法控制遊戲對象的行爲邏輯,至於方法的遊戲示例,會在本章後續內容講解結束之後給出。
在Unity中新建的腳本文件,裏面會自動添加一些代碼,如圖4-5所示。讀者在學習完方法之後,有沒有以爲自動添加的代碼中,Start()和Update()的書寫形式很像方法。沒錯,它們就是方法。只不過它們是Unity內置的方法,他們會被遊戲程序調用。
圖4-5 腳本中Unity自動添加的代碼
由於這兩個方法在腳本中很經常使用,因此Unity直接在新建的腳本中添加了它們。那麼,讀者可能要問了,這兩個方法會如何做用於遊戲對象呢?代碼中使用了註釋(雙斜槓「//」以及後面的部分就是註釋)對這兩個方法進行了簡單的說明:前者在初始化時被調用,後者在遊戲運行過程的每一幀被調用。若是讀者並不知足於註釋上的解釋,能夠考慮查閱Unity的幫助文檔。在第1章中,做者介紹過幫助文檔的打開和檢索方式,忘了的話能夠去複習如下。
現以查找Start()方法的使用說明爲例。在幫助文檔的檢索框中輸入MonoBehaviour.start,開始查找。通常狀況下會查找出不少結果,選擇須要的結果,打開它就能夠了。整個過程如圖4-6所示。
在幫助文檔中,會首先對這個方法的功能和使用步驟作簡要說明,並在最後給出這個方法的使用示例。
提示:Unity 的腳本可使用三種語言編寫,它們是C#、JavaScript和Boo,所以幫助文檔會給出分別使用這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行),實現的功能均是在Unity的Console視圖裏輸出一行文本信息。讀者能夠從輸出的信息中瞭解到,Start()和Update()的調用狀況。
(2)運行遊戲,此次觀察的焦點不是Game視圖,而是Console視圖,輸出的文本信息,如圖4-7所示。
圖4-7 Console視圖的文本信息輸出結果
經過Unity提供的幫助文檔,讀者應該瞭解到,方法Start()是在遊戲對象初始化的時候調用,且是在Update()前被調用。所以,Console視圖中首先輸出的是Start()方法裏的文本信息,然後Update()方法才被調用,所以隨後就輸出了Update()方法裏的文本信息。而且,因爲Update()方法在每幀都會被調用,所以Update()方法裏的文本信息會在遊戲運行的過程當中,持續輸出。
提示:若是讓Update()方法每幀都輸出信息的話,Console視圖很快就會被「刷屏」了。爲了阻止這種現象的發生,腳本代碼只是讓Update()方法每100幀輸出一次文本信息,可是Update()方法依然在每幀被調用。
出如今腳本中的方法,不管是在定義的時候,仍是使用的時候,後面都跟着一對括號「( )」,有意義嗎?看起來最多也就是起個快速識別方法的做用吧。既然C#的語法規定方法就應該這麼寫,確定是有必定道理的。若是是上升到戰略意義的道理,連做者也不是很明白,可是做者知道這對括號裏能夠添加「參數」。
要說明參數的做用,就必須從方法提及。方法能夠處理變量中的數據,進而影響遊戲對象的行爲邏輯,這是本章前面一直在強調的。可是就前面腳本中一直在使用的,方法的括號裏沒有參數的狀況而言,方法老是在處理特定變量裏的數據。例如,下面是前面一個示例中定義的方法:
int AddTwoNumber()
{
return number1 + number2;
}
這個方法的括號裏沒有參數,它處理的數據老是變量number1和number2裏的數據。既然這只是一個用於求和的方法,沒有必要指定它只計算變量number1和number2裏的數據和。若是有其它變量的數據也要求和的話,就只能再定義一個方法了。爲方法引入參數就能夠很好的解決這類的問題。
開發者定義了一個方法,能夠控制一個遊戲對象的邏輯行爲。若是其它對象也須要作出與之相似的行爲,就沒有必要再定義一個方法了。例以下面的遊戲示例所作的那樣。
(1)爲遊戲場景添加Cube、Cylinder和Directional light,這3個遊戲對象。前二者將做爲腳本方法控制行爲邏輯的遊戲對象,最後一個遊戲對象負責遊戲場景的照明。合理設置它們各自的位置,獲得的Scene和Game視圖,如圖4-8所示。
圖4-8 在Scene和Game視圖裏,查看各對象的相對位置,以及遊戲視圖的效果
(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 腳本代碼的12、15行,調用了兩次方法RotateObject(),前後傳入的參數也是不同的;
(3)將腳本MyScript賦予Main Camera對象,並在後者的Inspector視圖裏,設置My Script組件裏的My Cube和My Cylinder屬性爲遊戲場景中的Cube和Cylinder對象,屬性的設置方法是,直接拖動Hierarchy視圖裏的Cube和Cylinder對象到對應的屬性框中便可,如圖4-9所示。
圖4-9 設置My Script組件下的屬性
(4)運行遊戲,在Game視圖裏,一直按下鼠標左鍵,讀者會看到立方體對象在原地滾動。若是一直按下鼠標右鍵,那麼原地滾動的就成了圓柱體。若是同時按住鼠標左鍵和右鍵,立方體和圓柱體就會同時滾動了,如圖4-10所示。
圖4-10 遊戲效果展現圖
(5)遊戲中,控制遊戲對象滾動的方法是RotateObject(),它是一個須要傳入參數的方法。正是由於須要傳入參數,因此它才能被用於遊戲場景中,全部遊戲對象滾動的行爲邏輯控制中。而不僅是單獨的控制一個對象的行爲邏輯。
本文選自:C#遊戲開發快速入門大學霸內部資料,轉載請註明出處,尊重技術尊重IT人!