Unity3D如何有效地組織程式碼?

七大黍發表於2014-10-15


可以說是高度的Component-Based Architecture,
同時它的庫提供了大量的全域性變數。

準確地說,程式碼作為Unity專案裡的一種資源,此問題應該擴充套件到如何組織Unity資源。簡單說說我們的經驗:
1.  Unity有一些自身的約定,譬如專案裡的Editor,Plugins等目錄作為編輯器,外掛目錄等等。知名的外掛會自己存放一個目錄,譬如NGUI等。
所以我們自己的程式碼,一般目錄名會以下劃線開頭,譬如 "_Scripts", "_Prefabs"等。
對於場景,文件等目錄,用兩條下劃線,以便他們能排在最頂部。

2. 程式碼用C#,別用JS。必要的話用namespace將自己的程式碼括起來。我們是用namespace把自己積攢的公用庫包住。

3. C#的註釋要認真寫,打///就能幫你補全了,沒理由偷懶。

4. 每個程式檔案開頭要用一段註釋寫修改Log,誰改過什麼簡單留一條說明。就算用了Unity的版本管理或者Git,那些log終究會丟失,只有認真把log寫在程式碼裡,才會有意識去認真優化它。

5. Unity的指令碼邏輯,就功能而言大體分為兩種,一種是比較獨立的,譬如爆炸之後1秒鐘消失,這種單獨寫個指令碼繫結到目標上即可。


更多的是指令碼里與其它的指令碼進行互動。Unity裡提供了一種萬金油的方法是SendMessage, 這種方法效能略差,如果你呼叫的頻率不高,隨便用也無妨。另一種方法是直接通過物件的例項去呼叫。
我們的做法是寫幾個公用的控制器,讓它們各司其職,負責各自的事情:
1.  寫一個一個GlobalManager.cs來控制遊戲的全域性變數及全域性方法。靜態類模式。譬如當前玩到第幾大關第幾小關,玩家的金幣數量等。

2. 寫一個GameController.cs來控制當前關的遊戲程式。單例項模式。遊戲的主迴圈也是用它控制。初始化,勝利、失敗判定等等。

3. 寫一個InputController.cs來控制所有的使用者輸入。單例項模式。滑鼠、鍵盤、觸控式螢幕,我們做遊戲是保證同時支援這三種輸入的,因為大部分時間是在PC上測試。
關於GameController與InputController的聯絡,有點讓人糾結。一般來講是在InputContoller裡呼叫GameController.Instance.Foo()執行方法。或者直接對Input寫成Listener的模式,讓GameController去監聽。

4.  其它的類似選單控制器,聲音控制器,成就控制器,IAP虛擬道具控制器等等,也是採用類似的方法管理。

5.  關於PlayerPref的操作,統一寫成靜態類的get/set模式,程式中哪裡要用則直接讀寫。

6.  如果你的專案裡場景的數量少(<5),那麼拖入場景的資源可以很隨意。如果場景數量很多(幾十個,有的解謎遊戲每個關卡就是一個場景),那麼拖入場景的prefab數量一定要少。

7.  設計你的prefab資源裡,你要想像當其他人拿到這些資源,是否直接拖入一個空場景裡就能run,頂多再簡單設定幾下。如果你設計的資源不能做到這些,那麼得好好重新想想。


寫了這些,感覺寫不下去了。
想吃透Unity,起碼得真做出幾款產品放上線才行。真正做產品的過程中會碰到各種各樣意想不到的問題,程式碼不斷地被重構和妥協,不存在什麼最佳的方案。
暫時就寫這些吧,希望能拋磚引玉。

 

(PS:當然,這個是根據公司大專案來說的,每個公司都有自己定的規範和框架,略有不同。如果是想打飛機,2048這類的小遊戲是用不到這麼麻煩的。看看就好,知道一下)

 


相關文章