MVC:全名是Model-View-Controller
View(视图层 - 顶层)
Controller(控制层 - 中层)
Model(数据层 - 底层)
View(视图层)
说明:展现给玩家的(包括UI,包括场景中的一些表现)
注意:View层不能对Model的数据进行修改,但是能对Model的数据进行访问
功能:
1、数据的展现
2、管理自己面板的一些逻辑
3、实现用户界面的按钮的操作逻辑
Model(数据层)
说明:位于Frame最底层,属于数据中心
功能:
1、存放数据
2、提供修改访问数据的方法
3、通知View层数据已经发生改变,需要更新界面(通过事件)
Controller(控制层)
说明:对Model层具有访问和修改的权限。
功能:
1、根据逻辑对Model层的数据进行修改。
2、回调View的方法通知操作完成或者失败
MVC的优点:
1、工程结构更加的清晰
2、提高代码的可读性,封装性,扩展性
3、提高工作效率
游戏界面实例
画布尺寸1280x720
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211230745789-626650940.png)
把原图当作底图,调整透明度,去添加调整元素位置
描边组件
取消滑动条的交互
代码逻辑
视图层:
延迟函数问题:连续点击时会生成多个延迟函数,未消失的延迟函数,会影响到下次调用结果
代码逻辑
视图层:
延迟函数问题:连续点击时会生成多个延迟函数,未消失的延迟函数,会影响到下次调用结果
控制层:用单例模式抽象封装方法
提示界面问题:用委托和回调方法来实现
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController { private static PlayerController instance; public static PlayerController Instance { get { if (instance == null) { instance = new PlayerController(); } return instance; } } private PlayerController(){ } public delegate void Del(string str); /// <summary> /// 增加经验的方法,参数是增加的经验 /// </summary> /// <param name="exp"></param> public void AddExp(float exp) { //人物死亡不能获得经验 if (PlayerData.Instance.CurrentHP > 0) { PlayerData.Instance.CurrentExp += exp; //递归判断是否升级 CheckLevelUp(); } else { Debug.Log("人物死亡"); } } /// <summary> /// 使用递归判断是否升级 /// </summary> void CheckLevelUp() { if (PlayerData.Instance.CurrentExp >= PlayerData.Instance.MaxExp) { PlayerData.Instance.CurrentExp -= PlayerData.Instance.MaxExp; PlayerData.Instance.Level++; PlayerData.Instance.Gold += PlayerData.Instance.Level * 100;//每次升级需要增加玩家金币 CheckLevelUp(); } } /// <summary> /// 购买金币,参数的购买的 100 * num /// /// </summary> /// <param name="gold"></param> public void BuyGoldByDiamonds(int num, Del callback) { //金币比钻石 2 : 1 //判断钻石的数量是否够用 if (PlayerData.Instance.Diamonds >= (num * 100 * 0.5f)) { PlayerData.Instance.Diamonds -= (num * 50); PlayerData.Instance.Gold += (num * 100); } else { Debug.Log("钻石不足,请充值"); //告诉调用的人,钻石不够了 if (callback != null) { callback("钻石不足,请充值,没钱玩什么游戏!"); } } } public void Hit(float value, Del callback) { if (PlayerData.Instance.CurrentHP > 0) { PlayerData.Instance.CurrentHP = PlayerData.Instance.CurrentHP >= value ? PlayerData.Instance.CurrentHP - value : 0; } else { Debug.Log("玩家已经死亡"); if (callback != null) { callback("玩家已经死亡,不能鞭尸!!!!!"); } } } /// <summary> /// 通过金币购买血量 10 : 1 /// </summary> /// <param name="hp"></param> public void AddHPByGold(float hp) { if (PlayerData.Instance.CurrentHP <= 0) { Debug.Log("玩家已经死亡"); } else { int gold = (int)Mathf.Ceil(hp * 0.1f); if (PlayerData.Instance.Gold >= gold) { PlayerData.Instance.Gold -= gold; PlayerData.Instance.CurrentHP += hp; PlayerData.Instance.CurrentHP = PlayerData.Instance.CurrentHP > PlayerData.Instance.MaxHP ? PlayerData.Instance.MaxHP : PlayerData.Instance.CurrentHP; } else { Debug.Log("金币不够"); } } } public void ResetLife() { if (PlayerData.Instance.CurrentHP <= 0) { if (PlayerData.Instance.Diamonds >= 100) { PlayerData.Instance.Diamonds -= 100; PlayerData.Instance.CurrentHP = PlayerData.Instance.MaxHP * 0.5f; } else { Debug.Log("钻石不足, 请充值! 没钱,玩什么游戏!"); } } else { Debug.Log("玩家还没死呢,复什么活!"); } } /// <summary> /// 充值 /// </summary> public void Recharge(int diamonds) { PlayerData.Instance.Diamonds += diamonds; } }
数据层:用单例模式管理数据,提供修改访问数据的方法
数据刷新和同步问题:用属性对字段进行封装,用事件储存需要监控当前数据变化的界面的方法,当访问属性的时候,调用事件函数
using System.Collections; using System.Collections.Generic; using UnityEngine; //所有的数据都已经放在PlayerData里了 public class PlayerData { //未继承Mono的单例 //1、先有一个私有的静态的自己的实例 private static PlayerData instance; //2、提供一个访问实例的属性或者方法 public static PlayerData Instance { get { //判断实例是否为null if (instance == null) { instance = new PlayerData(); } return instance; } } public string PlayerName { get { return playerName; } set { if (playerName != value) { //通知界面更新 playerName = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public float MaxHP { get { return maxHP; } set { if (maxHP != value) { maxHP = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public float CurrentHP { get { return currentHP; } set { if (currentHP != value) { currentHP = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public float MaxExp { get { return maxExp; } set { if (maxExp != value) { maxExp = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public float CurrentExp { get { return currentExp; } set { if (currentExp != value) { currentExp = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public int Level { get { return level; } set { if (level != value) { level = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public int Gold { get { return gold; } set { if (gold != value) { gold = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } public int Diamonds { get { return diamonds; } set { if (diamonds != value) { diamonds = value; Debug.Log("值发生改变,更新界面"); UpdatePanel(); } } } //3、私有构造函数 private PlayerData() { //私有构造函数里进行数据的初始化 PlayerName = "寒冰射手"; MaxHP = 500; CurrentHP = 400; MaxExp = 1000; CurrentExp = 500; Level = 1; Gold = 500; Diamonds = 0; } private string playerName; private float maxHP; private float currentHP; private float maxExp; private float currentExp; private int level; private int gold; private int diamonds; //1.声明一个委托类型 public delegate void Del(); //2.声明一个事件变量 public event Del updateEvent;//这个事件里存储了所有的需要监控当前数据变化的界面的方法 void UpdatePanel() { //通知界面更新,不知道有多少界面, //可以使用委托=事件的方式,来通知所有的界面 if (updateEvent != null) { updateEvent(); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_Shop : MonoBehaviour { private Button expButton; private Button goldButton; private Button diamondsButton; private void Awake() { expButton = transform.Find("Button1").GetComponent<Button>(); goldButton = transform.Find("Button2").GetComponent<Button>(); diamondsButton = transform.Find("Button3").GetComponent<Button>(); expButton.onClick.AddListener(BuyExpClick); goldButton.onClick.AddListener(BuyGoldClick); diamondsButton.onClick.AddListener(BuyDiamondsClick); } void BuyExpClick() { PlayerController.Instance.AddExp(100); } void BuyGoldClick() { PlayerController.Instance.BuyGoldByDiamonds(1, null); } void BuyDiamondsClick() { PlayerController.Instance.Recharge(100); } // Use this for initialization void Start() { } // Update is called once per frame void Update() { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UGUI_Message : MonoBehaviour { private Text nameText; private Text hpText; private Text expText; private Text levelText; void Awake() { nameText = transform.Find("Text1").GetComponent<Text>(); hpText = transform.Find("Text2").GetComponent<Text>(); expText = transform.Find("Text3").GetComponent<Text>(); levelText = transform.Find("Text4").GetComponent<Text>(); //当数据改变时,需要更新界面,把更新界面的方法添加到PlayerData的事件里去 PlayerData.Instance.updateEvent += UpdatePanel; } // Use this for initialization void Start() { UpdatePanel();//数据初始化 } private void OnDestroy() { //当界面销毁的时候,不需要去监听数据的变化了,把事件移除 PlayerData.Instance.updateEvent -= UpdatePanel; } //数值发生改变的时候,更新界面 public void UpdatePanel() { nameText.text = "名字:" + PlayerData.Instance.PlayerName; hpText.text = "血量:" + ((int)PlayerData.Instance.CurrentHP).ToString() + "/" + ((int)PlayerData.Instance.MaxHP).ToString(); expText.text = "经验:" + ((int)PlayerData.Instance.CurrentExp).ToString() + "/" + ((int)PlayerData.Instance.MaxExp).ToString(); levelText.text = "等级:" + PlayerData.Instance.Level.ToString(); } }