#####该文章是个人学习MVC模式的总结和实践,水平有限,谢谢指点。
前言
在游戏开发的过程中,经常会遇到修改界面风格,但是界面的功能没有发生变化的情况。如果界面和逻辑可以分开,那么改动就会减少。MVC模式可以把界面的显示,操作,和数据分离,很适合经常修改的界面。
一、MVC模式是什么?
MVC全称为Model,View,Controller。
Model,模型,用于处理数据;
View,视图,用于显示模型中的数据,获取用户的输入;
Controller,控制器,用于根据视图的输入去更新模型中数据;
它们之间的关系是:
View监听用户输入,发送给Controller,Controller根据输入执行Model中对应的数据更新操作,Model中数据变化之后通知View,View收到通知就从Model中获取数据更新显示。
上图中的视图选择可能是一个Controller对应多个View,所以修改完数据之后需要选择由哪个View显示返回的数据。
需要注意的是View可以根据一定方法获取Model中的数据,但是不能修改,修改全部都要放在Model层。
二、unity中实现
1.整体流程
2.具体实现
实现了一个简单的UI,里面显示角色的基本信息。
MVC接口
/*
* Model接口
*/
public interface IUIModel
{
void Init();
}
/*
* View接口
*/
public interface IUIView
{
void PreInit(string path);
void ShowView(object data);
void HideView();
void Dispose();
}
/*
* Controller基类
*/
public interface IUIController
{
void PreInit(string path);
}
界面实现
public class RoleInfoModel : IUIModel
{
public string Name;
public string Quality;
public int Hp;
public int Attack;
public int Defense;
public void Init()
{
Name = "曹操";
Quality = "极品";
Hp = 100;
Attack = 200;
Defense = 300;
}
public void Upgrade()
{
Hp += 100;
Attack += 20;
Defense += 20;
GameEvents.TriggerEvent(eEventType.RoleInfo_OnUpgrade);
}
}
using UnityEngine.UI;
public class RoleInfoView : UIViewBase
{
private RoleInfoController _controller;
protected override IUIController controller
{
get
{
return _controller;
}
}
private Text roleName;
private Text quality;
private Text hp;
private Text attack;
private Text defense;
private Button upgrade;
private Button close;
public override void PreInit(string path)
{
base.PreInit(path);
roleName = transform.Find("bg/name").GetComponent<Text>();
quality = transform.Find("bg/qualityDesc/quality").GetComponent<Text>();
hp = transform.Find("bg/rightInfo/hp").GetComponent<Text>();
attack = transform.Find("bg/rightInfo/attack").GetComponent<Text>();
defense = transform.Find("bg/rightInfo/defense").GetComponent<Text>();
upgrade = transform.Find("bg/upgrade").GetComponent<Button>();
upgrade.onClick.AddListener(OnClickUpgrade);
close = transform.Find("bg/close").GetComponent<Button>();
close.onClick.AddListener(OnClickClose);
_controller = transform.GetComponent<RoleInfoController>();
_controller.PreInit(path);
}
public override void ShowView(object data)
{
RoleInfoModel model = MVCModels.GetModel(uiPath) as RoleInfoModel;
roleName.text = model.Name;
quality.text = model.Quality;
hp.text = model.Hp.ToString();
attack.text = model.Attack.ToString();
defense.text = model.Defense.ToString();
RegistEvents();
this.gameObject.SetActive(true);
}
public override void HideView()
{
this.gameObject.SetActive(false);
UnRegistEvents();
}
public override void Dispose()
{
}
private void OnClickUpgrade()
{
_controller.upgradeRole();
}
private void OnClickClose()
{
UIManager.Instance.HideUI(uiPath);
}
protected override void RegistEvents()
{
GameEvents.AddGameEvent(eEventType.RoleInfo_OnUpgrade, OnUpgraded);
}
protected override void UnRegistEvents()
{
GameEvents.RemoveGameEvent(eEventType.RoleInfo_OnUpgrade, OnUpgraded);
}
private void OnUpgraded()
{
RoleInfoModel model = MVCModels.GetModel(uiPath) as RoleInfoModel;
hp.text = model.Hp.ToString();
attack.text = model.Attack.ToString();
defense.text = model.Defense.ToString();
}
}
using UnityEngine;
public class RoleInfoController : MonoBehaviour, IUIController
{
private RoleInfoModel model;
public void PreInit(string path)
{
model = MVCModels.GetModel(path) as RoleInfoModel;
if (model == null)
{
model = new RoleInfoModel();
model.Init();
MVCModels.RegistModel(path, model);
}
}
public void upgradeRole()
{
model.Upgrade();
}
}
using System.Collections.Generic;
public class MVCModels
{
private static Dictionary<string, IUIModel> uiModels = new Dictionary<string, IUIModel>();
public static void RegistModel(string type, IUIModel model)
{
if (!uiModels.ContainsKey(type))
{
uiModels.Add(type, model);
}
}
public static IUIModel GetModel(string type)
{
if (uiModels.ContainsKey(type))
{
return uiModels[type];
}
return null;
}
}
MVCModels中存放所有界面的Model。
代码的绑定:
GameEvents是事件管理器,可以注册和分发事件。
eEventType是事件Id的枚举。
总结
使用MVC模式制作游戏界面可以让显示和数据解耦,代码层次清晰,易于理解。