unity 架構設計的學習


對於游戲開發而言,不同種類的游戲其架構方式都不同,並不存在什么完美架構模式某種類型是可以有分別的框架的,比如上帝視角ARPG,比如GAL,比如格斗,比如跑酷,比如卡牌,比如打飛機游戲。而他們使用的游戲架構自然也是不同的。通常來說游戲項目最合理的方式是由一個主程根據項目需求制定一套新的結構和各部分間的依賴關系,事先想好各個部分的拓展和通訊方式。有了這個過程,也就沒有硬是生搬硬套的再去套用什么模式(MVC之類).

一、一定程度上的邏輯代碼的分離,提高代碼的可維護性和 可重用性。

https://www.zhihu.com/question/23946609

我對Unity 代碼結構組織的困惑 ,經過各種查閱 ,發現其實主要是對於MonoBehaviour 上。mono必須是可是化的,要綁在GameObject上。 對於mono只做視覺上的效果,比如視覺上的特定效果(攝像機振動,飄血,特效,道具掉落,buff類),振動,變色,控制動畫,賦值點(控制行為參數數據),控制好它們的依賴,讓他們擁有通用性(比如道具掉落的動畫,UI動畫等),然后這些就不用再開發邏輯的時候去處理這些東西,可以丟一遍了。 而游戲的主體是一個空GameObject 上的腳本,它負責管理所有,分發事件。 其他的地方就不要出現MonoBehaviour了。

這樣處理的理由在於生命周期。 mono必須能看到,而邏輯往往會脫離於顯示部分,GameObject 未創建往往就需要有邏輯了。 也就是是說你創建一個人物,因該先創建一個MonoBehaviour類,然后在這個類的初始化代碼里創建一個GameObject 然后再套上各式MonoBehaviour,然后依然在這個非MonoBehaviour類處理定時邏輯和其他(定時邏輯,比如技能釋放,我釋放一個技能,由一個技能發射類管理這個技能特效的時效性)。需要時再控制下其他MonoBehaviour播放動畫、控制效果之類。 這就和其他非Unity游戲架構沒多大區別了。

對於MonoBehaviour的邏輯分離的一個理由在於,比如現在對角色進行控制,使用Character Manager、Controller (也可是說是FSM 、或者Behaviour Tree),來進行角色狀態間的控制,將它放在角色obj上。那通常只能是人物資源的那個GameObject。那么我有個需求是換狀態的時候切換為完整的另一個資源,那么要不是Compent復制要不是創建子級GameObject,無論哪個都不太好吧。

   或者,我想隱藏這個人物,包括里面的動畫啊和純顯示用邏輯,但是基本邏輯又想留着(否則什么時候才能恢復顯示?),本來直接將GameObject禁用就好了,現在這樣就不行了。或者說,它雖然有狀態,但並沒有顯示,而是一個虛擬對象。但如果它不是MonoBehavior就沒有任何問題了。這就是我所說的使用MonoBehavior的隱患,其實很多人心中都默默的有這樣的感覺吧?這個隱患也是確實存在的。

   當然我也不是說MonoBehavior就完全不能用,比如受創變色(切換以及根據color對所有Renderer賦值以及恢復為原材質)肯定是可以的,還有什么動畫順序播放,部件綁定。但是涉及到邏輯的部分,真的建議排除掉MonoBehavior。它確實是毒瘤。
此外有些人不喜歡MonoBehavior是因為start發生的不確定性,還有初始化沒有構造函數不便。那你需要端正下思路。你看unity默認的那些組件,你會在乎它們哪個先初始化嗎?你會在乎它有沒有構造函數參數嗎?你不會。因為它們設計成了你不需要考慮這些東西。所以如果你寫MonoBehavior,就應該設法按他們的模式走,讓初始化無需顧忌順序參數直接賦值就能解決,而不是拋棄start awake自己搞個create。
而MonoBehavior的主要優點就在於可以獨立使用,不依賴於環境。你建個預置拖上去設設參數就能看效果。這是它最大也是唯一的優點,它編碼上的不便也都是為了讓這一點成為可能。如果你的MonoBehavior做不到這一點,或者你認為不需要,那費老大勁搞成MonoBehavior又沒用,何苦。
二 、依舊是Unity 資源組織的問題

https://www.zhihu.com/question/21070379

- Unity有一些自身的約定,譬如項目里的Editor,Plugins等目錄作為編輯器,插件目錄等等。知名的插件會自己存放一個目錄,譬如NGUI等。
所以我們自己的代碼,一般目錄名會以下划線開頭,譬如 "_Scripts", "_Prefabs"等。
對於場景,文檔等目錄,用兩條下划線,以便他們能排在最頂部。
- 代碼用C#,別用JS。必要的話用namespace將自己的代碼括起來。我們是用namespace把自己積攢的公用庫包住。
- C#的注釋要認真寫,打///就能幫你補全了,沒理由偷懶。
- 每個程序文件開頭要用一段注釋寫修改Log,誰改過什么簡單留一條說明。就算用了Unity的版本管理或者Git,那些log終究會丟失,只有認真把log寫在代碼里,才會有意識去認真優化它。
- Unity的腳本邏輯,就功能而言大體分為兩種,一種是比較獨立的,譬如爆炸之后1秒鍾消失,這種單獨寫個腳本綁定到目標上即可。
更多的是腳本里與其它的腳本進行交互。Unity里提供了一種萬金油的方法是SendMessage, 這種方法性能略差,如果你調用的頻率不高,隨便用也無妨。另一種方法是直接通過對象的實例去調用。

我們的做法是寫幾個公用的控制器,讓它們各司其職,負責各自的事情:
- 寫一個一個GlobalManager.cs來控制游戲的全局變量及全局方法。靜態類模式。譬如當前玩到第幾大關第幾小關,玩家的金幣數量等。
- 寫一個GameController.cs來控制當前關的游戲進程。單實例模式。游戲的主循環也是用它控制。初始化,勝利、失敗判定等等。
- 寫一個InputController.cs來控制所有的用戶輸入。單實例模式。鼠標、鍵盤、觸摸屏,我們做游戲是保證同時支持這三種輸入的,因為大部分時間是在PC上測試。
關於GameController與InputController的聯系,有點讓人糾結。一般來講是在InputContoller里調用GameController.Instance.Foo()執行方法。或者直接對Input寫成Listener的模式,讓GameController去監聽。
- 其它的類似菜單控制器,聲音控制器,成就控制器,IAP虛擬道具控制器等等,也是采用類似的方法管理。
- 關於PlayerPref的操作,統一寫成靜態類的get/set模式,程序中哪里要用則直接讀寫。
- 如果你的項目里場景的數量少(<5),那么拖入場景的資源可以很隨意。如果場景數量很多(幾十個,有的解謎游戲每個關卡就是一個場景),那么拖入場景的prefab數量一定要少。
- 設計你的prefab資源里,你要想像當其他人拿到這些資源,是否直接拖入一個空場景里就能run,頂多再簡單設置幾下。如果你設計的資源不能做到這些,那么得好好重新想想。

三、代碼原則
著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
作者:feicheng wu
鏈接:https://www.zhihu.com/question/21070379/answer/24182335
來源:知乎

1.邏輯腳本基於場景划分
2.抽離靜態配置數據、全局管理數據以及對局臨時數據的管理
3.使用單例模式創建不依賴於場景的游戲對象及其上的全局管理器
4.避免使用GameObject.Find以及SendMessage,聲明對象引用以顯示標明腳本之間的依賴性,活用delegate解耦合
5.多用組合少用繼承(Component的架構真的是太棒了)
6.數據行為與邏輯表現分離,即V與MC的分離,換句話說多寫class少寫MonoBehavior。(通常初期在快速開發原型時會把一個功能全部實現寫在一個繼承於MonoBehavior的腳本中,盡早進行重構,抽離出負責數據管理與控制的類,這對於后期功能的增加與修改時很有必要的)
7.善用Coroutine(Coroutine真是太方便了)
8.盡量能夠使用自定義的配置文件輔助Prefab上腳本參數的配置。

總的來說記得知乎上看到誰說過cocos2d是程序員友好的,而Unity3D是設計師友好的,寫了這么多年Unity3D代碼我真是覺得我的思考方式越來越像策划而不是程序員了,使用Unity3D開發,寫代碼應該只占了大概50%的工作,另外50%都在編輯器上,如果你用過相信你懂得。


著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
作者:趙忠健
鏈接:https://www.zhihu.com/question/21070379/answer/65360313
來源:知乎

unity是基於組件開發 一上來確實不太適應,也跟同事討論了好久,至今沒什么太好的結論。說下我們的方案,
一.啟動場景一個 object上掛腳本主入口,他負責驅動游戲內所有manager的創建,更新及銷毀。
二.人物,AI等需要繼承的通過持有gameObject來是實現。而不是掛載到gameObject上。
三.基礎功能通過組件實現。掛載到gameObject上。(邏輯表現分離)
總體上就是最基礎層面 負責具體功能的用組件來降低耦合度,這樣也清晰。而一些需要始終存在的或者需要繼承則通過原來的方式,創建腳本對象,然后持有Object,這是這個object不在負責具體邏輯,只是各個基礎功能的總和。

著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
作者:歐宇龍
鏈接:https://www.zhihu.com/question/21070379/answer/76962412
來源:知乎

有句話,我總會仔細的跟很多朋友講到
做游戲,牛逼的不是實現某一個功能,而是把成百上千的功能放到一起,卻不亂。

而我認為,這條路,必須自己不斷總結反思。別人給的經驗,往往並不一定合適具體的項目。
不管別的,有幾個標准可以檢驗你的代碼是否合理

1:美術資源 提交后,策划配表提交后,不需要程序變換,即可立馬看到結果。 比如,一個圖標變了,美術可以打包圖集,提交。 策划變了一個配表,他可以直接提交配表。 一個新的怪物出現了,讓美術自己提交怪物資源..... 最后他們自己跑游戲里一看,發現東西是OK 的。
不管你程序如何設計,這事是最重要的一條。 簡單來說就是 讓美術和策划能夠提交后直接看到結果。

2:游戲暫停時,能否直接通過 視圖窗口,看到盡量多的游戲當前狀態。
以我做的ARPG為例,
再某一下,我一刀揮出去,打到一個怪物了。 再怪物受擊的那一瞬間,我點擊暫停。
這個時候我點擊怪物這個GameObject,可以看到怪物當前正在播放那個動畫,重力是多少,重力加速度是多少,受擊的效果有哪幾個,數值分別是多少... 可以通過視圖窗口看到當前怪物移動組件是否使用中,AI 組件是不是被停滯掉了
.........
這個點是存在爭議的,諸多從C++過來的朋友,cocos寫得多的朋友。並不習慣組件化這樣的東西

3:是否一個類只干一件事
這個同樣很重要
甚至可以說是需要被確保的。組件化或許這點有些爽。就是基本確保了你寫的某個組件只干一件事。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM