在Unity上進行開發,請先看對其開發模式應用的討論:
http://www.reddit.com/r/Unity3D/comments/1nb06h/unity_design_patterns_and_concepts_looking_for/
第一個問題,整個程序的入口在哪里。原來框架里的入口是個Scriptobject,用來啟動所有的管理器。在uFrame的架構里,設計一個GameManager繼承自Monobehaviour,然后利用DontdestroyOnLoad方法在不同的場景之間進行切換。
看看網上的各種討論,感覺uFrame不如SOC靠譜,后者用的人多,討論也多,抱着這顆大樹吧。
strangeioc提出了一個mvcs的框架,下面這個算是對框架各個部分一個比較清楚的說明
- Model – “I hold ALL of the data, ha ha ha.”
- View – “Hey, look at this” (graphics, gui, sound) and “Oh, you clicked the mouse” (input), “Either way I’ll tell the controller about it”.
- Controller – “Hey Model (or Service), someone clicked a button so do X or Y”, or “Service, you loaded? Ok, I’ll tell the model”, or “Thanks Model for the updated data, I’ll tell the view to show that”.
- Services – “Welcome everyone, I’m going to just load stuff from offline files and online servers and tell the controller”.
描述一個最基本的業務流程:
1.玩家點擊了一下UI
2.mediator得到通知(回調),因為它綁定了UI事件
3.mediator觸發了一次command執行指令,因為mediator和command進行了綁定
4.command執行自己的execute方法
5.請求Service從一個文件中讀取數據
6.Service讀取數據完成后,觸發事件通知Command執行execute函數。
7.command會把加載后的數據送給Model
8.Model檢測到自己更新數據后,通知mediator說有新數據來了
9.Mediator就會把數據送給UI,顯示到界面上。
原則:
View應該只負責顯示和輸入,當輸入事件發生時,view應當通知mediator,絕不能讓View直接通知給Model和Service,View只會分發事件,例如某個按鈕按下了,至於對這個按鈕的響應,應該交給Mediator來做,例如view告知說幫助按鈕按下了,mediator知道后,調用具體的command再去執行具體的任務。Model和Service是被Command來使用的,而不會去監聽view的事件。
StrangeIOC的例子
程序的入口是一個ContextView腳本,此腳本是個mb必須要掛在gameobject上,這應該也是命名帶上view的意思。這個ContextView里一般就是創建Context。
Context的功能把各個部分組合到了一起 。
分析一個StrangeRocks的例子
入口。此例子實現了類似飛行射擊類的游戲。分成了三個部分,入口,游戲模塊,UI,對應設計了三個場景,分別是main,game,ui,存放在Art的Scene目錄下。每個場景里都有一個節點,掛的是重寫的contextview腳本,分別是MainBootstrap,GameBootstrap,UIBootstrap.繼承關系如圖:
這其中每一個contextview腳本里都創建了一個context對象,分別是MainContext,GameContext,UIContext。這幾個類的集成關系如圖:
其中,crosstext可作為全局的定義,其他context可以訪問到。CrossContext里將會給ICrossContextInjectionBinder類型的變量 injectionBinder賦值。MVCSContext具備了搭建一個IOC應用的所有元素,包括( an Injector)注入器,(a message bus)消息總線,(Command
patterns)命令模式,(model and service support)模型支持,(View mediation)視圖中轉器等。
三個繼承的context ,都會重寫mapBindings函數。
1.MainContext里,會綁定全局的事件,綁定數據模型gamemodel為單件。
2.GameContext里,會綁定鍵盤輸入為單件,綁定精靈管理器,綁定技能管理器,定義了游戲過程中用到的各種池對象,包括特效,武器,精靈等。
隨后commandBinder,這里用的是SignalCommandBinder,來源於SignalContext的addCoreComponents方法里,把injectionBinder的ICommandBinder綁定為了SignalCommandBinder,這種binder就會把各種事件和對應的command執行器進行綁定。注意,這個command bind將會自動創建注入映射。最后是mediationBinder,用的是MediationBinder, 這個具體對象的綁定來源於MVCSContext的addCoreComponents方法,mediator的綁定將view和mediator結合到了一起。這就是說,context知道所有的細節,mediator不知道的,view不知道的,它都知道。
如何實現bind map to注入,有如下函數段:
其中command的注入過程是動態的,不是在bind的時候就綁定的,這樣也好理解,因為有可能我這個事件永遠不會發生,那就不需要綁定了:
嘗試實現精靈:
可以參考實現精靈的數據對象,例如ISpriteModel包含一個精靈需要的各種數據,包括血量,等級各種東西。然后是精靈的顯示對象,ISpriteView,這個view的作用是管理顯示相關的邏輯,即所有看得見的東西,例如移動,播放動畫,換裝,武器掛載,特效掛載,所有跟monobehaviour相關的,而Mecanim相關的事件必然是和gameobject相關的,所以必然是View相關的,gameobject上接收的所有事件都由View來接受,顯然這和他相關,是顯示。而比如當到達某個關鍵幀,需要觸發特效,讓view通知mediator再通知到controller,執行一次command。controller是個中轉環節,可以知道model,view,service等各種東西。這樣一來有可能就會設計的很復雜。command會有很多個,因為每個行為都是一個command,而不是一個controller。
strangeioc的Attribute竟然沒有給自己加命名空間,導致InjectAttribute.cs和nodecanvas里的Attribute命名沖突,nodecanvas是有自己的命名空間,strangeioc竟然沒有,略坑。
這里做個總結:
1.StrangeIOC的成熟度還不夠,用來做大型游戲項目顯然有些力不從心。至少目前沒有3A級的大作出來。
2.概念很多,在團隊中推廣難度很大,理解起來麻煩,各種事件調用機制 ,調試難度也很大。
3.MVC思想是務必會使用的,在各個模塊的設計過程中,都要有這個思想,數據,顯示,控制邏輯分開。但至於說是不是真要分的那么清楚,倒不用錙銖必究。
4.關於綁定框架。目前看在運行時,也許有些模塊可以做些小應用,但整個application范圍的應用需要慎重。
5.做這個框架的兩名工程師,可能沒做過大型的網絡游戲項目,這個框架套在網游上會很別扭,至少現在看來是的。
6.這個框架其實可以持續跟進,也許有一天,牛逼人就搞出來個牛逼的大作來。