Unity中使用簡易MVC詳解
來自專欄面向信仰
MVC概述
- MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟體設計典範。
- 根據名稱定義在MVC中可以分為三層,也就是Model 層,View 層,Controller 控制層
- Model(模型) :「數據模型」(Model)用於封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。模型有對數據直接訪問的權力,例如對資料庫的訪問。模型不依賴視圖和控制器,也就是說,模型不關心它會被如何顯示或是如何被操作。但是模型中數據的變化一般會通過一種刷新機制被公布。為了實現這種機制,那些用於監視此模型的視圖必須事先在此模型上註冊,從而,視圖可以了解在數據模型上發生的改變。 View(視圖) :視圖層能夠實現數據有目的的顯示(理論上,這不是必需的)。在視圖中一般沒有程序上的邏輯。為了實現視圖上的刷新功能,視圖需要訪問它監視的數據模型(Model),因此應該事先在被它監視的數據那裡註冊。 Controller(控制器) :控制器起到不同層面間的組織作用,用於控制應用程序的流程。它處理事件並作出響應。事件包括用戶的行為和數據模型上的改變
下圖展現了MVC不同層的類型和功能:
Unity中的MVC
- 在unity中常見並在大型項目中常用到的的ui框架有基於MVVM的uFrame、基於MVC的PureMVC和基於MVCS的StrangeIoC,三者各有優劣。關於這三個框架及MVVM和MVCS的結構我們之後再說,這裡通過代碼來了解一下在Unity中的MVC:
mvc核心控制類:
MVC.cs
using UnityEngine;using System;using System.Collections.Generic;/// <summary>/// puremvc核心控制器/// </summary>public class MVC : MonoBehaviour{ private static Dictionary<string, Model> Models = new Dictionary<string, Model>(); private static Dictionary<string, View> Views = new Dictionary<string, View>(); private static Dictionary<string, Type> Commands = new Dictionary<string, Type>(); #region Model Method /// <summary> /// 註冊model /// </summary> /// <param name="model">Model.</param> public static void RegisterModel(Model model) { if (!Models.ContainsKey(model.Name)) { Models.Add(model.Name, model); } } public static void UnRegisterModel(Model model) { if (Models.ContainsKey(model.Name)) { Models.Remove(model.Name); } } public static T GetModel<T>(string name) where T : Model { foreach (string n in Models.Keys) { if (n == name) { return Models[name] as T; } } return null; } #endregion #region View Method /// <summary> /// 註冊view /// </summary> /// <param name="view">View.</param> public static void RegisterView(View view) { if (!Views.ContainsKey(view.Name)) { Views.Add(view.Name, view); } } public static void UnRegisterView(View view) { if (Views.ContainsKey(view.Name)) { Views.Remove(view.Name); view.RegisterNotification(); } } public static T GetView<T>(string name) where T : View { foreach (string n in Views.Keys) { if (n == name) { return Views[name] as T; } } return null; } #endregion #region Command Method /// <summary> /// 註冊controller /// </summary> /// <param name="name">Name.</param> /// <param name="type">Type.</param> public static void RegisterCommand(string name, Type type){ if (!Commands.ContainsKey(name)){ Commands.Add(name, type); } } public static void UnRegisterCommand(string name, Type type){ if(Commands.ContainsKey(name)){ Commands.Remove(name); } } public static void HandleNotifition(string name, object data = null){ //判斷事件是否存在,如果存在則實例化對象並執行事件 if(Commands.ContainsKey(name)){ Controller command = Activator.CreateInstance(Commands[name]) as Controller; command.Execute(data); } //判斷視圖是否關注該事件,如果關注則執行事件 foreach(View view in Views.Values){ if (view.ContainsNotification(name)){ view.HandleNotification(name, data); } } } #endregion}
Model基類
Model.cs:
using UnityEngine;/// <summary>/// mov中的Model基類/// </summary>public abstract class Model{ /// <summary> /// model的名字 /// </summary> /// <value>The name.</value> public abstract string Name { get; } /// <summary> /// 發送通知 /// </summary> /// <param name="name">事件名稱</param> /// <param name="data">事件執行參數</param> public virtual void SendNotification(string name, object data = null){ MVC.HandleNotifition(name, data); }}
View基類
View.cs
using UnityEngine;using System.Collections.Generic;/// <summary>/// mvc中的View基類/// </summary>public abstract class View{ /// <summary> /// View的名字 /// </summary> /// <value>The name.</value> public abstract string Name { get; } /// <summary> /// 發送通知 /// </summary> /// <param name="name">事件名稱</param> /// <param name="data">事件執行參數</param> public virtual void SendNotification(string name, object data = null){ MVC.HandleNotifition(name, data); } /// <summary> /// 獲取模型model /// </summary> /// <returns>The model.</returns> /// <param name="name">model名稱</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public T GetModel<T>(string name) where T : Model{ return MVC.GetModel<T>(name) as T; } /// <summary> /// 保存通知 /// </summary> private List<string> InterestNotification = new List<string>(); public virtual void RegisterNotification(){ } public bool ContainsNotification(string name){ return InterestNotification.Contains(name); } /// <summary> /// 處理事件 /// </summary> /// <param name="name">事件名稱</param> /// <param name="data">事件參數</param> public virtual void HandleNotification(string name, object data = null){ }}
Controller基類
Controller.cs
using UnityEngine;using System;/// <summary>/// mvc中的Controller基類/// </summary>public abstract class Controller{ /// <summary> /// Controller的名字 /// </summary> /// <value>The name.</value> public abstract string Name { get; } public T GetModel<T>(string name) where T : Model { return MVC.GetModel<T>(name); } public T GetView<T>(string name) where T : View { return MVC.GetView<T>(name); } public void RegisterView(View view) { MVC.RegisterView(view); } public void RegisterModel(Model model) { MVC.RegisterModel(model); } public void RegisterCommand(string name, Type type) { MVC.UnRegisterCommand(name, type); } /// <summary> /// 發送通知 /// </summary> /// <param name="data">事件執行參數</param> public abstract void Execute(object data = null);}
寫在最後
- 這裡只是為了介紹unity中mvc的簡單使用,但於我看來,在遊戲項目中mvc框架並不非常適用,MVC是ui專用的模式,遊戲不同於web前端,不同類型的遊戲其架構相差非常之大(比如棋牌類遊戲,rpg遊戲,moba類遊戲,跑酷類遊戲之間的差別) ,所以遊戲中mvc不同的層很難有非常清晰的定義。並不是說MVC在遊戲項目中完全沒用,但只有它還遠遠不夠。遊戲項目最合理的方式是由主程根據項目需求制定一套新的結構和各部分的依賴關係,並事先想好各部分的擴展和通信方式。
推薦閱讀: