本文我們簡單聊一下,游戲開發中的MVC架構。
遊戲中的MVC架構
預告
- 本文包含以下內容:
- 一種MVC在遊戲開發中的可能的例子。
- 該例子的完全實現細節和可能踩坑。
- C#高階語法(含高階繼承、反射、委託等)。
- 本文適合以下群眾閱讀:
- 對遊戲開發感興趣的人
- 有C#使用基礎(、UNITY引擎經驗)的人
- 已經接觸過MVC(Model-View-Controller)框架的人。
- 本文不適合以下群眾閱讀:
- 網絡噴子
- 完全不懂編程的人
正文
以下開始正式的內容,先簡單介紹概念,然後介紹實現,最後做一個總結。
概念介紹
沒想到吧,游戲開發中也有MVC,大概的思路是分開Model管理數據,View管理引用,Controller管理邏輯。
傳統的MVC框架
先聊聊傳統的MVC框架吧,傳統的MVC框架是
- Model:與儲存數據
- Controller:管理數據的操作
- View:管理數據展示相關的操作
可能如果完全沒有開發經驗的話(其實不適合閱讀本文,本文對你收益不大,建議繼續閱讀前及時補充相應知識和經驗。),不太理解為什麼我們要拆分開來,這些框架究竟是幹什麼的?
這裡的框架是用來約束你的行為的,讓你能快速理解你在做什麼,你可能會覺得我為什麼會不知道為什麼我會迷離?你可能現在不會迷離,但是假如時間上經過一年、五年、十年呢?如果你需要管理大量系統邏輯和對應的底層實現呢?如果你是在別人的基礎上開展工作呢?你要重寫嗎?
軟件開發已經脫離了個人時代,進入了團隊合作的時代。框架是可以用來指導開發者的行為,降低群體間合作的成本的,一方面可以互相劃分工作,另一方面可以降低理解門檻。在初期時期,你可能寫過幾百上千行的main函數,後來你就會明白要分函數,要抽象邏輯,函數之間可以互相組合達到更大的表達力,這就是另一個問題了2333。另一方面,你可以劃分文件,讓一切都是“可管理”的,普通人能同時管理的物體數目似乎就是7-13(憑印象,取自代碼大全),因而做合理的劃分是十分有必要的。
你可能無法提出一些框架,大部分人實際上也不需要提出,我們能從根本目的理解框架的目的、按規則去使用,如此就可以了。
讓少數天才的工作為更多人服務,不是很棒嗎?
遊戲中的MVC框架
在JohnDoeWorld的開發時期,已經初步理解到隨著設計上的希望擴充,底層代碼量的狂野生長,當時主要采用單例模式,盡可能的將方法的使用抽象出來,即便如此,還是沒能分出更多的精力去把表現層次上的問題修復。
在不久之前的Project.DL,因爲是一個人業餘在做,基本上已經被折騰到了極限,感覺各種東西都混到一起,只有實現當時能理清究竟什麽是幹什麽的,事後多半就變成一鍋粥(其實...這是個通用的問題)
Memento項目初期,從開發那裏接觸到了游戲開發中的MVC這一説,試著去翻了一下實現,然後自己獨立於UNITY引擎用新的.Net Core 3.0給實現了一番,這也就是這篇文章的由來了。
擧一些具體的例子來講吧,如果你使用Unity開發,你是需要操控游戲中的具體物體的,於是你多半需要存儲一個引用——不管是靜態的賦值、還是動態的搜索,而這個關聯,我們就可以放在View層,對應之前的和界面相關的内容。
Model層依然存儲數據,不過這裏的數據就是獨立於游戲物體的更加抽象的數據了,Controller層就儲存對數據的操作。
實現相關
可以參考MVC.DotNet。
從具體的代碼一層層開始談起吧。
- Model-View-Controller
- Model: 普通類(結構體)
- View: 繼承Behavior,視遊戲引擎接口而定
- Controller: 對應具體Model View,且保存其引用;
- 繼承Caller允許根據Command類型調用不同Command
- Command-Caller-Core
- Command:虛函數GetController
- Caller:繼承Behavior,含通用的調用Command方法Call,實現交由Core部分處理
- Core:核心部分
- 保存所有View、Model、Controller、Command對應邏輯,使用Dict,用Type做Key
- 對於Command調用,首先拿到Controller
- 第一次使用,如果不存在,則去創造
- 然後使用反射找到OnCommand邏輯
- 提供通過字符名直接反射找到方法
- Exception, etc.
- Exception,外圍異常類,放置需要額外操作。
語法細節
建議直接閱讀源碼和MSDN相關參考,這裡不展開來說了。