關於Unity的一些概念和語法
最近一直在利用空閒時間看Unity的API,看的比較細但是實際操作的比較少,昨天有一整天的空閒時間,再加上有了一個還不錯的想法,想要把它實現出來,因為用到的模型並不複雜,不需要用到建模軟體,也不用到處去搞素材,貼圖就隨手從收集的圖片裡做點篩選和剪下的工作,一切看上去很容易搞定,於是開始著手寫程式碼。我從基本的GUI開始寫,登陸框,主選單,這是進入遊戲的基本途徑,然後NEW GAME進入遊戲的第一關,這裡好戲才剛剛開始。
我花了不少時間在挑選貼圖和嘗試不同的shader上,這些不是重點,當我寫到使用者輸入字元檢測的時候傻眼了,我在Unity Answer上面搜到一些程式碼,有載入System.RegularExpression(載入一部分多餘的程式碼,而我希望儘量把遊戲的體積控制在最小)然後用正則表示式做replace的,也有比較簡單的字元比較,用Event.current.character與字元'a','z','A','Z','0','9'進行比較,這是在C#裡的程式碼,在UnityScript裡會提示不能把String型別轉換成char型別,這個問題牽扯的就比較多了。既然UnityScript不會把String自動轉換成char,那我就手動來轉換吧?但是對基本型別的方法Unity的文件裡基本上沒有提及,那麼Unity是怎麼處理String,char,Array這些基本型別的?
這裡要澄清一些關鍵的概念。Unity提供三種指令碼供我們使用,C#,js和Boo,javascript程式設計師可能覺得用js會很得心應手,但是不要被表象所迷惑。這個js和我們熟知的ECMA版js有著天大的區別,這就是為什麼我傾向於稱其為UntyScript而不是javascript的原因,它沒有js的無型別宣告,沒有物件直接量和函式直接量,沒有prototype的繼承機制,卻多了類,聯合,extent繼承等等。UnityScript是由Boo語言實現的,Boo執行在Mono虛擬機器上,轉換成原生代碼執行,而Mono是一個開源的.net框架。在用到UnityScript的基本型別比如char,String,Array只有直接去查Mono的文件。
上面提到的使用者名稱校驗問題實際上用char的一個方法isLetterOrDigit就能輕鬆解決,但是如果沒去看Mono的文件我肯定不知道這點。
說到UnityScript和Javascript的區別,其實官方wiki上有個比較詳盡的帖子,我也是用到這些東西,一頭扎入繁雜的程式碼細節中,才發現這些問題,當然有些東西平時也自然而然的用到了,比如var s:int;這樣的寫法,在js裡則是var s;為了避免型別檢測的開銷用強型別宣告是很有必要的。另外還有一些需要注意的地方:
- 在js中變數宣告前的var有些情況下是可以省略的,但是unity中如果宣告一個變數沒有用var,這個變數的作用域就是全域性的。
- 沒有prototype繼承機制,繼承的語法:class Foo extents Bar { };
- 可以定義虛擬函式,這樣子類可以重寫它,語法是virtual function Do(){ something; },在父類和子類中都要加virtual關鍵字
- 在子類中調父類的方法,使用super關鍵字,比如class Foo extents Bar{ virtual function Do(){ super.Do(); /*...more code..*/ }; }
- 比繼承方便簡潔的方法是,直接獲取父類元件名,使用它的方法,用到Unity提供的函式GetComponent(),另外還有個小技巧,如果在某個腳本里使用static宣告一個變數,在其他指令碼直接用指令碼名.變數就可訪問,不用GetComponent()
- String用下標操作得到char型別,比如"foobar"[3]得到char型別的字元'b'
- UnityScript每個指令碼都是繼承自Monobehaviour的一個類,這點在C#和Boo裡需要顯式宣告,但是在UnityScript裡是隱含和自動完成的,每個指令碼名就是一個類名,也就是一個型別名稱,在指令碼的全域性環境裡宣告的變數實際上是宣告為這個指令碼類的屬性,全域性函式實際上是它的方法,在這個類裡也可以定義其他的類
- UnityScript裡有兩種陣列,基本的array以及javascript類似的Array,陣列直接量如[1, 2, 3]屬於array型別,只能用下標操作,不能用push這樣的方法,要宣告一個Array必須用var a = new Array()這樣的語句,推薦使用.net的List替代它,宣告方法和C#有點小區別:var myList = new List.<int>();注意中間的點符號
- UnityScript裡使用列舉:enum SomeEnum { aaa, bbb, ccc, ddd };
- 因為UnityScript是執行在Mono上的,可以使用Mono庫,用import System; import System.IO(在Unity裡進行檔案操作,可以用這個,比如System.IO.File.Open()來開啟一個檔案)
- 因為UnityScript是執行在Mono上的,可以使用第三方的庫,比如XML-RPC.net等,用import關鍵字引入其.dll檔案