对MVC思想简单说明
MVC思想就是一种让View(视图(UI界面))、Data(数据)之间分离,通过中介Controller(管理逻辑脚本)进行交互的一种框架思想,目的是为了减少代码的耦合性。
MVC全名是Model View Controller,是模型(Model)👉 视图(View)👉 控制器(Controller)的缩写,是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
M 👉 V 👉 C
1、M(模型) 处理应用程序数据逻辑的部分 👉 通常模型对象负责在数据库中存取数据。
2、V(视图) 是应用程序中处理数据显示的部分 👉 通常视图是依据模型数据创建的。
3、C(控制器) 是应用程序中处理用户交互的部分 👉 通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据(管理相关逻辑)。
4.注意:1、Unity~MVC是一种非必须UI系统开发框架 2、主要用于开发游戏UI系统逻辑
5.优点:降低耦合性,方法修改,逻辑更清晰
6.缺点(1、有一定的性能消耗(如今的电脑配置基本可以忽略))
普通方法与MVC思想脚本进行对比
普通方法脚本如👇:
代码少、体积小、逻辑复杂😥
MVC思想脚本如👇:
脚本分开管理逻辑更加清晰😀
使用的UI预制体
最后效果
使用普通方法完成案例
图示如👇:
1、PlayerGradeManager
usingUnityEngine; usingUnityEngine.UI; publicclassPlayerGradeManager : MonoBehaviour{ //正常写法 通常四部走 获取对应组件 👉 添加事件 👉 更新信息 👉 动态显示//1、获取对应组件publicTexttxtLev; publicButtonplayerBut; privatestaticPlayerGradeManagerplayerGradeManageG; publicstaticPlayerGradeManagerPlayerGradeManageG { get=>playerGradeManageG; } //2、添加事件privatevoidStart() { playerBut.onClick.AddListener(() => { //打开角色面板的逻辑PlayerInfoManager.ShowMe(); }); } //3、更新信息publicvoidUpdateInfo() { //获取玩家数据 更新数据//获取数据方法 1、网格请求 2、json 3、xml 4、2进制 5、PlayerPrefs公共类//这里通过PlayerPrefs来获取本地存储的玩家信息 更新信息界面上txtLev.text="等级:"+PlayerPrefs.GetInt("LevValue", 1).ToString(); } //4、动态显示publicstaticvoidShowMe() { if (PlayerGradeManageG==null) { GameObjectres=Resources.Load<GameObject>("UI/PlayerGrade"); GameObjectobj=Instantiate(res); //设置他的位置obj.transform.SetParent(GameObject.Find("Canvas").transform, false); //获取自身脚本playerGradeManageG=obj.GetComponent<PlayerGradeManager>(); } //创建完后显示PlayerGradeManageG.gameObject.SetActive(true); //更新面板后同步数据PlayerGradeManageG.UpdateInfo(); } publicstaticvoidHideMe() { //方式一 :直接删除//if (playerGradeManager != null)//{// Destroy(playerGradeManager.gameObject);// playerGradeManager = null;//}//方式二 :隐藏PlayerGradeManageG.gameObject.SetActive(false); } }
2、PlayerInfoManager
usingUnityEngine; usingUnityEngine.UI; publicclassPlayerInfoManager : MonoBehaviour{ //正常写法 通常四部走//1、获取对应组件publicTextplayerAttack; publicTexthp; publicTextdefense; publicTexttxtLev; publicButtonupgrade; publicButtonhideBag; privatestaticPlayerInfoManagerplayerInfo; //2、添加事件privatevoidStart() { upgrade.onClick.AddListener(() => { Debug.Log("sasd"); //升级相关逻辑UpLev(); }); hideBag.onClick.AddListener(() => { //隐藏面板HideMe(); }); } //3、更新信息privatevoidUpdateInfo() { //获取玩家数据 更新数据//获取数据方法 1、网格请求 2、json 3、xml 4、2进制 5、PlayerPrefs公共类//这里通过PlayerPrefs来获取本地存储的玩家信息 更新信息界面上txtLev.text=PlayerPrefs.GetInt("LevValue",1).ToString(); playerAttack.text=PlayerPrefs.GetInt("AttackValue", 888).ToString(); hp.text=PlayerPrefs.GetInt("HpValue", 888).ToString(); defense.text=PlayerPrefs.GetInt("DefenseValue", 888).ToString(); } //4、动态显示publicstaticvoidShowMe() { if (playerInfo==null) { GameObjectres=Resources.Load<GameObject>("UI/PlayerInfo"); GameObjectobj=Instantiate(res); //设置他的位置obj.transform.SetParent(GameObject.Find("Canvas").transform, false); //获取自身脚本playerInfo=obj.GetComponent<PlayerInfoManager>(); } //创建完后显示playerInfo.gameObject.SetActive(true); //更新面板后同步数据playerInfo.UpdateInfo(); } publicstaticvoidHideMe() { //方式一 :直接删除//if (playerGradeManager != null)//{// Destroy(playerGradeManager.gameObject);// playerGradeManager = null;//}//方式二 :隐藏playerInfo.gameObject.SetActive(false); } //升级相关逻辑privatevoidUpLev() { //获取数据intLevValueInt=PlayerPrefs.GetInt("LevValue", 1); intAttackValueInt=PlayerPrefs.GetInt("AttackValue", 888); intHpValueInt=PlayerPrefs.GetInt("HpValue", 888); intDefenseValueInt=PlayerPrefs.GetInt("DefenseValue", 888); //更新磁盘里面的数据intadd=50; LevValueInt+=add; AttackValueInt+=add; HpValueInt+=add; DefenseValueInt+=add; PlayerPrefs.SetInt("LevValue", LevValueInt); PlayerPrefs.SetInt("AttackValue", AttackValueInt); PlayerPrefs.SetInt("HpValue", HpValueInt); PlayerPrefs.SetInt("DefenseValue", DefenseValueInt); //同步面板数据UpdateInfo(); //同步PlayerGradeManager~UI界面的数据PlayerGradeManager.PlayerGradeManageG.UpdateInfo(); } }
3、UI_Evenemt (UI事件)
usingUnityEngine; publicclassUI_Evenemt : MonoBehaviour{ privateboolisShowBag; privatevoidUpdate() { if (Input.GetKeyDown(KeyCode.B)) { //显示隐藏面板isShowBag=!isShowBag; if (isShowBag) PlayerGradeManager.ShowMe(); elsePlayerGradeManager.HideMe(); } } }
使用MVC思想完成案例
图示如👇:
1、Controller
PlayerGradeController
usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; //MVC中的C 👉 1、Controller负责相关逻辑 👉 2、界面事件监听等 处理对应的业务逻辑 👉 3、界面更新publicclassPlayerGradeController : MonoBehaviour{ //在Controller获取View 简单理解?? C控制VprivatePlayerGradeViewplayerGradeView; privatestaticPlayerGradeControllerplayerGradeControllerC=null; publicstaticPlayerGradeControllerPlayerGradeControllerC { get=>playerGradeControllerC;} privatevoidStart() { //获取View脚本 👉 第一次更新界面 👉 监听事件处理相关逻辑//获取View脚本playerGradeView=GetComponent<PlayerGradeView>(); //更新界面playerGradeView.UpdateInfo(ModeData.Instance); //事件监听playerGradeView.playerBut.onClick.AddListener(() => { PlayerInfoController.ShowMe(); }); //添加委托事件ModeData.Instance.AddEvent(UpdateInFo); } //见面的显示与隐藏publicstaticvoidShowMe() { if (playerGradeControllerC==null) { //实例化UI对象GameObjectres=Resources.Load<GameObject>("UI/PlayerGradeS"); GameObjectobj=Instantiate(res); //设置其位置到Canvasobj.transform.SetParent(GameObject.Find("Canvas").transform,false); //判断是否实例过playerGradeControllerC=obj.GetComponent<PlayerGradeController>(); } playerGradeControllerC.gameObject.SetActive(true); } publicstaticvoidHideMe() { //方式一 :直接删除//if (playerGradeManager != null)//{// Destroy(playerGradeManager.gameObject);// playerGradeManager = null;//}//方式二 :隐藏if(playerGradeControllerC!=null) playerGradeControllerC.gameObject.SetActive(false); } //更新同步数据privatevoidUpdateInFo(ModeDatafunction) { playerGradeView.UpdateInfo(function); } }
PlayerInfoController
usingSystem; usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; //MVC中的C 👉 1、Controller负责相关逻辑 👉 2、界面事件监听等 处理对应的业务逻辑 👉 3、界面更新……publicclassPlayerInfoController : MonoBehaviour{ //在Controller获取View 简单理解 👉 C控制VprivatePlayerInfoViewplayerInfoView; privatestaticPlayerInfoControllerplayerInfoControllerC=null; publicstaticPlayerInfoControllerPlayerInfoControllerC { get=>playerInfoControllerC; } privatevoidStart() { //获取View脚本 👉 第一次更新界面 👉 监听事件处理相关逻辑//获取View脚本playerInfoView=GetComponent<PlayerInfoView>(); //更新界面playerInfoView.UpdateInfo(ModeData.Instance); //添加委托事件ModeData.Instance.AddEvent(UpdateInFo); //事件监听playerInfoView.upgrade.onClick.AddListener(() => { ModeData.Instance.UpLev(); }); playerInfoView.hideBag.onClick.AddListener(() => { HideMe(); }); } //见面的显示与隐藏publicstaticvoidShowMe() { if (playerInfoControllerC==null) { //实例化UI对象GameObjectres=Resources.Load<GameObject>("UI/PlayerInfoS"); GameObjectobj=Instantiate(res); //设置其位置到Canvasobj.transform.SetParent(GameObject.Find("Canvas").transform, false); //判断是否实例过playerInfoControllerC=obj.GetComponent<PlayerInfoController>(); } playerInfoControllerC.gameObject.SetActive(true); } privatestaticvoidHideMe() { //方式一 :直接删除//if (playerGradeManager != null)//{// Destroy(playerGradeManager.gameObject);// playerGradeManager = null;//}//方式二 :隐藏if (playerInfoControllerC!=null) playerInfoControllerC.gameObject.SetActive(false); } //更新同步数据privatevoidUpdateInFo(ModeDatafunction) { playerInfoView.UpdateInfo(function); } }
2、ModelData
ModeData
usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; usingUnityEngine.Events; //MVC中的M 👉 储存数据publicclassModeData{ //MVC 👉 M一般流程 如👇://1、数据内容 ?? 2、数据相关操作&&初始化 ……?? 3、更新数据 ?? 4、储存数据 ……//1、数据内容privateintplayerLve; privateintlev; privateintattackValue; privateinthp; privateintdefense; publicintPlayerLve { get=>playerLve; } publicintLev { get=>lev;} publicintAttackValue { get=>attackValue;} publicintHp { get=>hp;} publicintDefense { get=>defense;} //使用单例用于外部调用 (M一般情况:自己是个静态单例 或者 存在一个单例模式对象中)privatestaticModeDatainstance=null; publicstaticModeDataInstance { get { if (instance==null) { instance=newModeData(); instance.Init(); } returninstance; } } //使用MVC思想不能从M去调用 其他的事件…… (使用事件)privateeventUnityAction<ModeData>updateDataEvent; //2、数据相关操作 (初始化……)publicvoidInit() { //初始化数据playerLve=PlayerPrefs.GetInt("LevValue", 1); lev=PlayerPrefs.GetInt("LevValue", 1); attackValue=PlayerPrefs.GetInt("AttackValue", 888); hp=PlayerPrefs.GetInt("HpValue", 888); defense=PlayerPrefs.GetInt("DefenseValue", 888); } //3、更新本地数据publicvoidUpLev() { intadd=50; playerLve+=add; lev+=add; attackValue+=add; hp+=add; defense+=add; Save(); } //4、储存数据publicvoidSave() { PlayerPrefs.SetInt("LevValue", lev); PlayerPrefs.SetInt("LevValue", lev); PlayerPrefs.SetInt("AttackValue", attackValue); PlayerPrefs.SetInt("HpValue", hp); PlayerPrefs.SetInt("DefenseValue", defense); UpdateInFo(); } //添加事件publicvoidAddEvent(UnityAction<ModeData>function) { updateDataEvent+=function; } //移除事件publicvoidRemoveEvent(UnityAction<ModeData>function) { updateDataEvent-=function; } //使用事件通知外部更新数据privatevoidUpdateInFo() { //第一种写法 👇//if (updateDataEvent != null)//{// updateDataEvent(this);//}//第二种写法 👇updateDataEvent?.Invoke(this); } }
3、View
PlayerGradeView
usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; usingUnityEngine.UI; //MVC中的V 👉 1、完成控件的查找 👉 2、提供UI更新的方法给外部publicclassPlayerGradeView : MonoBehaviour{ //1、完成控件的查找publicTexttxtLev; publicButtonplayerBut; //2、提供UI更新的方法给外部publicvoidUpdateInfo(ModeDatamodeData) { txtLev.text="等级:"+modeData.PlayerLve.ToString(); } }
PlayerInfoView
usingSystem.Collections; usingSystem.Collections.Generic; usingUnityEngine; usingUnityEngine.UI; //MVC中的V 👉 1、完成控件的查找 👉 2、提供UI更新的方法给外部……publicclassPlayerInfoView : MonoBehaviour{ //1、完成控件的查找publicTexttxtLev; publicTextplayerAttack; publicTexthp; publicTextdefense; publicButtonupgrade; publicButtonhideBag; //2、提供UI更新的方法给外部publicvoidUpdateInfo(ModeDatamodeData) { txtLev.text=modeData.Lev.ToString(); playerAttack.text=modeData.AttackValue.ToString(); hp.text=modeData.Hp.ToString(); defense.text=modeData.Defense.ToString(); } }
最后
下篇文章再见ヾ( ̄▽ ̄)ByeBye