Unity3D熱更新LuaFramework入門實戰(7)——PureMVC

LuaFramework使用了PureMVC框架。百度百科上說:「PureMVC是在基於模型、視圖和控制器MVC模式建立的一個輕量級的應用框架」。PureMVC框架可以做到較好的解耦,減少遊戲代碼的相互調用。然而LuaFramework整合PureMVC屬於「殺雞用牛刀」,實質上只用到了事件分發(也可能是我理解得不夠透徹)。如果單純寫一套事件分發系統,可能不到100行代碼就能完成。

by 羅培羽

1、解耦的好處

如果沒有很好的解耦設計,遊戲功能越多,代碼就越亂,最後沒人敢改動。舉個例子,假如遊戲中背包(item)和成就(Achieve)兩項功能,各用一個類實現。當玩家獲得100個經驗豆(一種道具)時,會獲得「擁有100個經驗豆」的成就;當成就點數達到300時,會獲得道具獎勵。一種常見的實現方法是調用對方的public函數,代碼如下所示。然而如果一款遊戲有幾百上千個類,之間又相互調用,如果某些功能需要大改(例如刪掉成就功能),那其他的類也得改動。

Class Itemn{n public AddItem()n {n if(經驗豆 > 100)n achieve.AddAchieve(「擁有100個經驗豆」)n }n}n nClass Achieven{n public AddAchieve()n {n 成就點數 + 10n if(成就點數 > 300)n item.AddItem(寶石)n }n}n

如果使用事件分發,各個類之間的聯繫就減弱了。如下所示的代碼中背包類(Item)監聽了消息「添加道具」,成就類(Achieve)監聽了消息「添加成就」。如果達成成就需要添加獎勵,只需派發「添加道具」這條消息,由背包類去執行。這樣類與類之間不存在相互調用,就算大改功能甚至刪掉功能,其他類都受到的影響比較小。

Class Itemn{n Start()n {n 監聽(「添加道具」,AddItem)n }nn private AddItem()n {n if(經驗豆 > 100)n 分發(「添加成就」,「擁有100個經驗豆」)n }n}n nClass Achieven{n Start()n {n 監聽(「添加成就」,AddAchieve)n }n n private AddAchieve()n {n 成就點數 + 10n If(成就點數 > 300)n 分發(「添加道具」, 寶石)n }n}n

2、MVC的使用方法

LuaFramework中的Framwork目錄存放著PureMVC框架的代碼,個人認為在LuaFramework中屬於過度設計(畢竟從其他地方拷過來的)。它的原理並不複雜,用一個列表把監聽信息保存起來,在派發消息時,查找對應的監聽表,找到需要回調的對象。

PureMVC框架便是實現了「註冊/分發」模式(發布/訂閱、觀察者模式),可以調用RegisterCommand註冊消息(命令),調用SendMessageCommand方法分發消息。RegisterCommand方法可以把某個繼承ControllerCommand 的類註冊到指定的消息下,在事件分發時調用該類的Execute方法。

例如新建一個名為TestCommand的類,讓它繼承ControllerCommand,然後編寫Execute方法處理具體事務。

using UnityEngine;nusing System.Collections;n npublic class TestCommand : ControllerCommand n{ntpublic override void Execute(IMessage message) nt{nttDebug.Log("name=" + message.Name);nttDebug.Log("type=" + message.Type);nt}n}n

接著,編寫另一個類來處理消息。這個類先調用AppFacade.Instance.RegisterCommand()將TestCommand類註冊到「TestMessage」消息下。然後使用SendMessageCommand()派發「TestMessage」消息。框架將會創建一個TestCommand實例,並調用它的Execute方法。

public class Main : MonoBehaviour n{n void Start() nt{nttAppFacade.Instance.RegisterCommand ("TestMessage", nttttttttypeof(TestCommand));nttAppFacade.Instance.SendMessageCommand ("TestMessage");n }n}n

運行結果如下所示,可以看到分發消息後,TestCommand的Execute方法被調用。

Execute方法的參數message包含了Name,Body,Type三個成員(如下圖所示)。其中Name是命令名,Body是一個任意類型的參數。

如下代碼所示,在SendMessageCommand中可以給消息的Body傳值,相應的Execute方法便可以獲取它。

void Start() n{ntAppFacade.Instance.RegisterCommand ("TestMessage", nttttttttypeof(TestCommand));ntAppFacade.Instance.SendMessageCommand ("TestMessage", "這是字元串");n}n

運行結果如下圖所示。

總而言之,LuaFramework中所謂的pureMVC只是一套「註冊/分發」機制,完全可以用c#的事件來實現。另《Unity3D網路遊戲實戰》中的客戶端網路模塊部分也使用的「註冊/分發」機制,有興趣的讀者可以看看。

3、MVC與Unity3D組件的結合

pureMVC與Unity3D組件之間有一些封裝,只要讓組件繼承View類(View類繼承MonoBehavior),即使用pureMVC框架的RegisterMessage和SendMessageComman方法實現「註冊/分發」機制。

例如,新建一個繼承自View的TestManage組件,在Start 方法中它註冊了「msg1」、「msg2」、「msg3」三個消息的監聽。在Update方法中,當按下空格鍵時,分發消息「msg1」。

當接收到消息後,指定對象(這裡指定this)的OnMessage方法會被調用,參數message裡面包含了命令名、Body等信息。代碼如下所示。

using UnityEngine;nusing System.Collections;nusing System.Collections.Generic;n npublic class TestManage : View n{n nt// Use this for initializationntvoid Start () nt{nttList<string> regList = new List<string>();nttregList.Add("msg1");nttregList.Add("msg2");nttregList.Add("msg3");n nttRegisterMessage(this,regList);nt}ntnt// Update is called once per framentvoid Update () nt{nttif (Input.GetKeyUp (KeyCode.Space)) ntt{ntttfacade.SendMessageCommand("msg1", null);ntt}nt}n ntpublic override void OnMessage(IMessage message) nt{nttDebug.Log ("OnMessage " + message.Name);nt}n}n

此外LuaFramework的各個Manager(如GameManager,LuaManager,SoundManager等)也都繼承自View類,可以使用「註冊/分發」機制。

後記

也許我對pureMVC的設計理解不足,但在LuaFramework中,我依然認為它過度設計。最後依然是廣告時間。

筆者即將出版的一本Unity3D實戰類書籍《Unity3D網路遊戲實戰》。通過一個完整的多人坦克對戰實例,詳細介紹網路遊戲開發過程中涉及到的知識和技巧。書中還介紹了服務端框架、客戶端網路模塊、UI系統的架構等內容。下圖為《Unity3D網路遊戲實戰》的示例遊戲。

其他一些文章的連接:

Unity3D熱更新LuaFramework入門實戰(1)——代碼熱更新

zhuanlan.zhihu.com/p/21

Unity3D熱更新LuaFramework入門實戰(2)——資源熱更新

zhuanlan.zhihu.com/p/21

Unity3D熱更新LuaFramework入門實戰(3)——編寫Lua邏輯

zhuanlan.zhihu.com/p/21

AR仙劍:一款手機應用,配合手機或pad使用,能將二次元動漫人物零距離展現在你的身旁!

pal5h.com/arpal/

《不會電腦也彙編》筆者N多年前寫的彙編教程

pan.baidu.com/s/1pJBs1m


推薦閱讀:

Unity自動化構建之iOS打包(另有Android篇)
微表面模型-PBR渲染管線的材質
Unity線性空間下移動設備上烘焙變暗問題處理
UWA GOT v1.1 | 支持本地管理深度測評、全新的UWA API、兼容Unity 2017.3

TAG:Unity游戏引擎 | Lua编程 | MVC |