unity3d框架mvc_unity3d mvc框架 - CSDN
  • MVC在桌面应用程序,以及网页架构上面用的比较多,那么怎么应用到Unity3d中呢,下面就带大家去了解这个设计框架,以及如何在Unity中应用。 二、MVC介绍 简介 MVC全名是Model View Controller...

    一、前言

    MVC是一种比较常见的设计框架,是一种将代码的功能进行划分的一种设计框架,主要原理就是将软件用户界面和业务逻辑分离,以使代码可扩展性、可复用性、可维护性、灵活性加强。
    MVC在桌面应用程序,以及网页架构上面用的比较多,那么怎么应用到Unity3d中呢,下面就带大家去了解这个设计框架,以及如何在Unity中应用。

    二、MVC介绍

    简介

    MVC全名是Model View Controller,是模型(Model)-视图(View)-控制器(Controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

    Model(模型) 是应用程序中用于处理应用程序数据逻辑的部分。
      通常模型对象负责在数据库中存取数据。
    View(视图) 是应用程序中处理数据显示的部分。
      通常视图是依据模型数据创建的。
    Controller(控制器) 是应用程序中处理用户交互的部分。
      通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
      
    MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。

    模型-视图-控制器(MVC)是Xerox PARC在二十世纪八十年代为编程语言Smalltalk-80发明的一种软件设计模式,已被广泛使用。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。

    MVC的业务流程

    在这里插入图片描述

    MVC是设计模式吗

    MVC是一种设计模式,但是却不在Gof总结过的23种设计模式中,所以确切说MVC不是一个设计模式,而是多种设计模式的组合,而不仅仅只是一个设计模式。
    组成MVC的三个模式分别是组合模式、策咯模式、观察者模式,MVC在软件开发中发挥的威力,最终离不开这三个模式的默契配合。 那些崇尚设计模式无用论的程序员,请了解只要你们使用MVC,就离不开设计模式。
    组合模式只在视图层活动, 视图层的实现用的就是组合模式,当然,这里指的实现是底层的实现,是由编程框架厂商做的事情,用不着普通程序员插手。

    组合模式的类层次结构是树状的, 而我们做Web时视图层是html页面,html的结构不正是树状的吗,这其实就是一个组合模式的应用,只是浏览器厂商已经把界面相关的工作帮我们做掉了,但它确确实实是我们应用MVC的其中一部分,只是我们感觉不到罢了,这也是我们觉得View是实现起来最简单最没有歧义的一层的原因。

    除网页以外的其他用户界面程序,如WPF、Android、ASP.NET等等都是使用树状结构来组织界面控件对象的,因为组合模式就是从界面设计的通用解决方案总提炼出来的。所以与其说MVC选择了组合模式,还不如说组合模式是必定会存在MVC中的,因为只要涉及到用户界面,组合模式就必定存。事实上即使不理解组合模式,也不影响程序员正确的使用MVC,组合模式本就存在于程序员接触不到的位置。

    然而,观察者模式和策略模式就显得比较重要,是实实在在MVC中接触的到的部分。

    观察者模式有两部分组成,被观察的对象和观察者,观察者也被称为监听者。对应到MVC中,Model是被观察的对象,View是观察者,Model层一旦发生变化,View层即被通知更新。View层和Model层互相之间是持有引用的。 我们在开发Web MVC程序时,因为视图层的html和Model层的业务逻辑之间隔了一个http,所以不能显示的进行关联,但是他们观察者和收听者的关系却没有改变。当View通过http提交数据给服务器,服务器上的Model接受到数据执行某些操作,再通过http响应将结果回送给View,View(浏览器)接受到数据更新界面,这不正是一个接受到通知并执行更新的行为吗,是观察者模式的另一种表现形式。

    但是,脱离Web,当通过代码去纯粹的表示一个MVC结构的时候,View和Model间无疑是观察者和被观察的关系,是以观察者模式为理论基础的。即使在Web中因为http壁垒的原因导致真正的实现有点走样,但是原理核心和思路哲学却是不变的。

    最后是策略模式。策略模式是View和Controller之间的关系,Controller是View的一个策略,Controller对于View是可替换的, View和Controller的关系是一对多,在实际的开发场景中,也经常会碰到一个View被多个Controller引用,这即使策咯模式的一种体现,只是不那么直观而已。

    总结一下,关于MVC各层之间关系所对应的设计模式

    View层,单独实现了组合模式

    Model层和View层,实现了观察者模式

    View层和Controller层,实现了策咯模式

    MVC就是将这三个设计模式在一起用了,将这三个设计模式弄明白,MVC将毫无神秘感可言。如果不了解这三个设计模式去学习MVC,那不管怎么学总归是一知半解,用的时候也难免不会出想问题。

    三、参考文章

    深入理解MVC https://blog.csdn.net/zuiyingong6567/article/details/80150834
    MVC简介 https://www.cnblogs.com/diyunfei/p/6752618.html
    【Unity】MVC框架 https://blog.csdn.net/qq_39574690/article/details/80757261
    Unity中MVC简单应用 https://www.jianshu.com/p/acc689be52f9
    【Unity3D】手游开发实践《腾讯桌球》客户端开发经验总结 https://blog.csdn.net/q764424567/article/details/81020381
    MVC框架 https://baike.baidu.com/item/MVC%E6%A1%86%E6%9E%B6/9241230?fr=aladdin&fromid=85990&fromtitle=MVC

    四、Unity中使用MVC

    在这里插入图片描述
    本篇文章主要是讲一下我是如何在Unity中使用MVC模式,MVC模式肯定不能照搬进Unity中,所以很多东西都做了修改,以适合我的项目使用,如果有不对的地方,希望大家能指正出来。

    使用原理

    在这里插入图片描述
    代码文档结构就是这样的
    目前我了解的MVC应用到Unity中只有两种模式,一种就是先按照业务功能划分,再按照MVC划分
    在这里插入图片描述
    蛋糕心语游戏就是这种模式,使得模块更聚焦(高内聚)
    第二种就是先按照MVC划分,然后再分出来业务功能
    在这里插入图片描述
    第二种方式用多了发现随着项目的运营模块增多,没有第一种那么好维护。

    MVC的关键就在于业务划分,代码分离,其实跟三层架构比较相似,把业务层、逻辑层、数据层分开来,互相通过一个接口进行调用,但是并不知道接口是怎么实现的。

    所以现在的问题就在于如何去划分呢。

    实现:
    Model(模型层):
    在这一层主要就是存放用户的数据,UI的数据,静态字段,数据存储,以及模型贴图资源的存储
    比如说:

    • 存放静态字段
      在这里插入图片描述
    • 存放数据
      在这里插入图片描述
    • 存放模型材质字段
      在这里插入图片描述
    • 数据库增删改查操作
      在这里插入图片描述

    View(视图层)
    在这一层主要是放一些UI参数,获取UI数据,获取按钮事件等
    在这里插入图片描述
    在这里插入图片描述
    点击事件
    在这里插入图片描述

    Controller(控制层)
    这一层就是去实现业务逻辑功能,获取Model的数据,通知View层更新数据,承上启下的功能
    在这里插入图片描述

    五、实例

    就带大家实现在Untiy中使用MVC模式,实现更换图片的功能
    步骤一:设计界面
    在这里插入图片描述
    在这里插入图片描述
    步骤二:MVC搭建
    Model_Main.cs
    在这里插入图片描述
    View_Main.cs
    在这里插入图片描述
    Controller_Main.cs
    在这里插入图片描述
    在这里插入图片描述

    关于那个鼠标点击事件那个方法,在我另一篇文章中有讲到,不懂的可以去那篇帖子仔细看一下。
    https://blog.csdn.net/q764424567/article/details/82424308
    效果:
    在这里插入图片描述
    源代码已经上传到CSDN,按需下载
    https://download.csdn.net/download/q764424567/10768387

    六、总结

    PS:程序员最重要的就是总结,不然学的再多到关键时刻用不上还是白搭,总结梳理,然后写下来,当快忘了的时候可以回来看看,会有不一样的体悟哦。
    在Unity中应用MVC模式已经讲解完了,MVC模式其实就是多种设计模式的结合体,也是三层架构的改良产品,基本原理就是把业务逻辑、功能实现、数据给分开来,利于增加功能,和维护。
    俗话说的好,一千个人就有一千个哈姆雷特,每个人研究MVC之后,运用到Unity中的方法都不尽相同,方法也是很多样,我主要就是提供一个想法和思路,更多优化运用还要大家多开动脑筋咯。
    最后,再回顾一下
    Model(数据层):存放静态字段、数据存储、模型资源存储
    View(视图层):就是用户可以看到的层,指的是可以看到的UI,模型,加载和调用事件
    Controller(管理层):实现业务逻辑功能、加载模型资源、功能实现等

    展开全文
  • 模型Model脚本(GameModel)using UnityEngine; using System.Collections; using System.Collections.Generic; //model是双向的,中间的 public class GameModel : MonoBehaviour { //委托model去通知自身view(是用...

    这里写图片描述
    这里写图片描述
    模型Model脚本(GameModel)

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    //model是双向的,中间的
    public class GameModel : MonoBehaviour {
    
        //委托model去通知自身view(是用事件完成的),实例---(通知改变)
        public event UpdateDataEventHandle updateDataEvent;
    
    
        //玩家名称
        private string playerName;
        //玩家经验
        private float playerExperience;
        //玩家等级
        private float playerLevel;
    
    
    
        public string PlayerName {
            get {
                return playerName;
            }
            set {
                playerName = value;
                //当值发生改变的时候直接调用更新(通知改变)
                updateDataEvent (playerName, playerExperience, playerLevel);
            }
        }
    
    
        public float PlayerExperience {
            get {
                return playerExperience;
            }
            set {
                playerExperience = value;
                updateDataEvent (playerName, playerExperience, playerLevel);
            }
        }
    
    
        public float PlayerLevel {
            get {
                return playerLevel;
            }
            set {
                playerLevel = value;
                updateDataEvent (playerName, playerExperience, playerLevel);
            }
        }
    }
    

    控制器Controller脚本(GameController)

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    //控制器主要是初始化,以及按钮的事件
    public class GameController : MonoBehaviour {
    
        public static GameController instance;
    
        private GameModel mod;
    
        private GameView view;
    
        void Awake(){
            instance = this;
            mod = GetComponent<GameModel> ();//绑定model
            view = GameObject.Find ("Canvas").GetComponent<GameView> ();//绑定View
        }
        void Start(){
            //mod里的委托事件与view绑定(通知改变事件)
            mod.updateDataEvent += view.UpdateViewData;
            ModelInit ();
        }
        void ModelInit(){
        //附上初始值
            mod.PlayerExperience=0;
            mod.PlayerLevel = 1;
            mod.PlayerName="frank901";
        }
        /// <summary>
        /// 按钮事件方法(用户请求)
        /// </summary>
        public void OnButtonClick(){
            //controller通知model(状态改变)
            mod.PlayerExperience += 30;
            if (mod.PlayerExperience >= mod.PlayerLevel * 100) {
                mod.PlayerExperience -= mod.PlayerLevel * 100;
                mod.PlayerLevel++;
            }
        }
    }
    

    视图View脚本(GameView)

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    //View主要是UI,监听,中心的显示
    
    public delegate void UpdateDataEventHandle(string name,float experience,float level);//因为是事件(通知改变)所以用到委托
    
    public class GameView : MonoBehaviour {
    
        private InputField showBox;
        private Button addExBtn;
    
        void Awake(){
            //找到UI对象
            showBox = transform.Find ("InputField").GetComponent<InputField> ();
            addExBtn = transform.Find ("Button").GetComponent<Button> ();
        }
        //为了防止出现空引用,依据mono生命周期的执行顺序,所以把调用单例放在Start里
        void Start(){
            //绑定GameController的回调(用户请求事件)
            addExBtn.onClick.AddListener(GameController.instance.OnButtonClick);
        }
        //更新数据,通知改变(从model到view)是一个事件(通知改变)
        public void UpdateViewData(string name,float experience,float level){
            showBox.text = "Name:" + name + "Experience:" + experience.ToString() + "level:" + level;
        }
    }
    

    这里写图片描述

    展开全文
  • Unity 3D MVC 框架

    2019-10-09 11:02:18
    UIManager using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace MyMVC { public enum UILayerRoot { None = 0, BaseLayer, ...

     UIManager

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    namespace MyMVC
    {
        public enum UILayerRoot
        {
            None = 0,
            BaseLayer,
            PopWindowLayer,
            TopLayer,
            Count,
        }
        public class UIManager
        {
            private static GameObject canvasObj;
            private static Camera uiCamera;
            private static Canvas canvas;
            private static CanvasScaler canvasScaler;
            private static GObjectFindTool findTool;
            private static Dictionary<UILayerRoot, RectTransform> layerRoots = new Dictionary<UILayerRoot, RectTransform>();
            private static Dictionary<Type, UIBase> openUIs = new Dictionary<Type, UIBase>();
            private static Dictionary<Type, UIBase> closeUIs = new Dictionary<Type, UIBase>();
            private static Dictionary<UILayerRoot, List<UIBase>> openUIsOnLayer = new Dictionary<UILayerRoot, List<UIBase>>();
            private static Dictionary<UIBase, UIMediatorBase> uiAndMediators = new Dictionary<UIBase, UIMediatorBase>();
    
            public static void Init()
            {
                canvasObj = GameObject.Find("Canvas");
                if (canvasObj == null)
                {
                    return;
                }
                UnityEngine.Object.DontDestroyOnLoad(canvasObj);
                findTool = GObjectFindTool.Create(canvasObj);
                uiCamera = findTool.GetComponent<Camera>("UICamera");
                uiCamera.clearFlags = CameraClearFlags.Depth;
                canvas = findTool.GetComponent<Canvas>("Canvas");
                canvasScaler = findTool.GetComponent<CanvasScaler>("Canvas");
                canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
                float sw = canvas.pixelRect.width / canvas.scaleFactor;
                float sh = canvas.pixelRect.height / canvas.scaleFactor;
                if (sw != 0 && sh != 0)
                {
                    float f = sw > sh ? sh / sw : sw / sh;
                    canvasScaler.matchWidthOrHeight = f;
                }
                InitUILayerRoots();
            }
            private static void InitUILayerRoots()
            {
                AddOnUILayerRoot(UILayerRoot.BaseLayer, findTool.GetComponent<RectTransform>("BaseLayer"), 0);
                AddOnUILayerRoot(UILayerRoot.PopWindowLayer, findTool.GetComponent<RectTransform>("PopWindowLayer"), -2000);
                AddOnUILayerRoot(UILayerRoot.TopLayer, findTool.GetComponent<RectTransform>("TopLayer"), -4000);
            }
            private static void AddOnUILayerRoot(UILayerRoot layerType, RectTransform tra, float z)
            {
                layerRoots[layerType] = tra;
                Vector3 pos = tra.anchoredPosition3D;
                tra.anchoredPosition3D = new Vector3(pos.x, pos.y, z);
            }
            public static void OnDestroy()
            {
                layerRoots.Clear();
                openUIs.Clear();
                closeUIs.Clear();
                openUIsOnLayer.Clear();
                uiAndMediators.Clear();
            }
            public static UIBase Show<TUI, TMediator>(UILayerRoot layer = UILayerRoot.BaseLayer) where TUI : UIBase where TMediator : UIMediatorBase
            {
                return Show(typeof(TUI), typeof(TMediator), layer);
            }
            private static UIBase Show(Type uiType, Type mediatorType, UILayerRoot layer)
            {
                UIBase ui;
                if (openUIs.TryGetValue(uiType, out ui))
                {
                    return ui;
                }
                if (!closeUIs.TryGetValue(uiType, out ui))
                {
                    ui = CreateUI(uiType);
                }
                ui.gameObject.transform.SetParent(layerRoots[layer], false);
                InitUIBase(uiType, ui, mediatorType);
                UpdateLayer(layer, ui);
                return ui;
            }
            public static UIBase CreateUI(Type uiType)
            {
                UIBase ui;
                string path = uiType.GetField("ResourcesPath").GetValue(null).ToString();
                GameObject prefab = ResourcesMgr.LoadPrefab("UIPrefabs/" + path);
                if (prefab == null)
                {
                    Debug.Log("Cannot find " + path);
                    return null;
                }
                prefab.name = path;
                ui = prefab.AddComponent(uiType) as UIBase;
                return ui;
            }
            private static void InitUIBase(Type uiType, UIBase ui, Type mediatorType)
            {
                openUIs[uiType] = ui;
                UIMediatorBase mediator = BindMediator(ui, mediatorType);
                ui.gameObject.SetActive(true);
                mediator.OnShow();
            }
            private static UIMediatorBase BindMediator(UIBase ui, Type mediatorType)
            {
                UIMediatorBase mediator = Activator.CreateInstance(mediatorType, new object[] { ui }) as UIMediatorBase;
                uiAndMediators[ui] = mediator;
                return mediator;
            }
            private static void UnBindMediator(UIBase ui)
            {
                UIMediatorBase mediator;
                if (uiAndMediators.TryGetValue(ui, out mediator))
                {
                    MessageManager.UnRegister(mediator);
                }
                uiAndMediators.Remove(ui);
            }
            private static void UpdateLayer(UILayerRoot layer, UIBase ui, bool isShow = true)
            {
                ui.SetUILayerRoot(layer);
                if (!openUIsOnLayer.ContainsKey(layer))
                {
                    openUIsOnLayer[layer] = new List<UIBase>();
                }
                List<UIBase> uis;
                if (openUIsOnLayer.TryGetValue(layer, out uis))
                {
                    if (isShow)
                    {
                        if (!uis.Contains(ui))
                        {
                            uis.Add(ui);
                        }
                        else
                        {
                            uis.Remove(ui);
                            uis.Add(ui);
                        }
                    }
                    else
                    {
                        uis.Remove(ui);
                    }
                    for (int i = 0; i < uis.Count; i++)
                    {
                        uis[i].SetSiblingIndex(i);
                    }
                }
            }
            public static void CloseUI<TUI>() where TUI : UIBase
            {
                CloseUI(typeof(TUI));
            }
            private static void CloseUI(Type uiType)
            {
                UIBase ui;
                if (openUIs.TryGetValue(uiType, out ui))
                {
                    UnBindMediator(ui);
                    openUIs.Remove(uiType);
                    ui.gameObject.SetActive(false);
                    closeUIs[uiType] = ui;
                    UpdateLayer(ui.GetUILayerRoot(), ui, false);
                }
            }
        }
    }

    UIBase

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using UnityEngine;
    using UnityEngine.EventSystems;
    
    namespace MyMVC
    {
        public class UIBase : MonoBehaviour
        {
            public const string ResourcesPath = "";
            private int siblingIndex;
            private UILayerRoot uiLayer = UILayerRoot.BaseLayer;
            private GObjectFindTool findTool;
    
            protected GObjectFindTool FindTool
            {
                get
                {
                    if (findTool == null)
                    {
                        findTool = GObjectFindTool.Create(gameObject);
                    }
                    return findTool;
                }
            }
            protected GameObject GetObj(string objName)
            {
                return FindTool.GetObject(objName);
            }
            protected T GetCom<T>(string objName) where T : Component
            {
                return FindTool.GetComponent<T>(objName);
            }
            public virtual void InitUI() { }
            public void BindButtons(object mediatorObj, List<string> btnNames, string methodPre = "OnClick")
            {
                Type objType = mediatorObj.GetType();
                for (int i = 0; i < btnNames.Count; i++)
                {
                    string btnName = btnNames[i];
                    GameObject btnObj = FindTool.GetObject(btnName);
                    if (btnObj == null)
                    {
                        Debug.Log("Cannot find " + btnName);
                        continue;
                    }
                    string methodName = methodPre + btnName;
                    if (objType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) == null)
                    {
                        Debug.Log("Cannot find " + methodName);
                        continue;
                    }
                    Action<PointerEventData> func = (Action<PointerEventData>)Delegate.CreateDelegate(typeof(Action<PointerEventData>), mediatorObj, methodName, true, false);
                    if (func == null)
                    {
                        Debug.Log("Cannot CreateDelegate Action<PointerEventData> " + methodName);
                        continue;
                    }
                    UIEvent.Get(btnObj).OnPointerClickCallBack = func;
                }
            }
            public void SetSiblingIndex(int index)
            {
                siblingIndex = index;
                if (transform.GetSiblingIndex() != siblingIndex)
                {
                    transform.SetSiblingIndex(siblingIndex);
                }
            }
            public void SetUILayerRoot(UILayerRoot layer)
            {
                uiLayer = layer;
            }
            public UILayerRoot GetUILayerRoot()
            {
                return uiLayer;
            }
        }
    }

     组件获取工具类 GObjectFindTool

    using System.Collections.Generic;
    using UnityEngine;
    
    namespace MyMVC
    {
        public class GObjectFindTool
        {
            private Dictionary<string, GameObject> objectDic = new Dictionary<string, GameObject>();
    
            public GObjectFindTool(GameObject obj)
            {
                RegObject(obj);
            }
    
            public static GObjectFindTool Create(GameObject obj)
            {
                return new GObjectFindTool(obj);
            }
    
            public void RegObject(GameObject obj)
            {
                Transform[] trs = obj.GetComponentsInChildren<Transform>(true);
                for (int i = 0; i < trs.Length; i++)
                {
                    Transform item = trs[i];
                    objectDic[item.name.ToLower()] = item.gameObject;
                }
                string sn = obj.name.ToLower();
                if (sn.Contains("(clone)"))
                {
                    sn.Replace("(clone)", "");
                }
                objectDic[sn] = obj;
            }
    
            public static Transform GetObject(GameObject obj, string findName)
            {
                Transform[] trs = obj.GetComponentsInChildren<Transform>(true);
                for (int i = 0; i < trs.Length; i++)
                {
                    Transform item = trs[i];
                    if (item.name == findName)
                    {
                        return item;
                    }
                }
                return null;
            }
    
            public bool HasObject(string objName)
            {
                if (string.IsNullOrEmpty(objName))
                {
                    return false;
                }
                objName = objName.ToLower();
                return objectDic.ContainsKey(objName);
            }
    
            public GameObject GetObject(string objName)
            {
                if (string.IsNullOrEmpty(objName))
                {
                    return null;
                }
                objName = objName.ToLower();
                GameObject obj = null;
                if (objectDic.TryGetValue(objName, out obj))
                {
                    return obj;
                }
                return null;
            }
    
            public T GetComponent<T>(string objName) where T : Component
            {
                if (string.IsNullOrEmpty(objName))
                {
                    return null;
                }
                GameObject cobj = GetObject(objName);
                if (cobj == null)
                {
                    return null;
                }
                return cobj.GetComponent<T>();
            }
        }
    }

     加载类 ResourcesMgr

    using System.Collections.Generic;
    using UnityEngine;
    
    namespace MyMVC
    {
        public class ResourcesMgr
        {
            private static Dictionary<string, object> pool = new Dictionary<string, object>();
            private static T Load<T>(string path) where T : Object
            {
                if (pool.ContainsKey(path))
                {
                    return pool[path] as T;
                }
                T obj = Resources.Load<T>(path);
                pool[path] = obj;
                return obj;
            }
            public static T LoadObj<T>(string path) where T : Object
            {
                return Load<T>(path);
            }
            public static GameObject LoadPrefab(string path)
            {
                return Object.Instantiate(Load<GameObject>(path));
            }
            public static void ClearPool()
            {
                pool.Clear();
            }
        }
    }

     按钮注册相关 UIEvent

    using System;
    using UnityEngine;
    using UnityEngine.EventSystems;
    
    namespace MyMVC
    {
        public class UIEvent : EventTrigger
        {
            public static UIEvent Get(GameObject obj)
            {
                UIEvent e = obj.GetComponent<UIEvent>();
                if (e == null)
                {
                    e = obj.AddComponent<UIEvent>();
                }
                return e;
            }
    
            public Action<PointerEventData> OnPointerClickCallBack;
            public Action<PointerEventData> OnPointerDownCallBack;
            public Action<PointerEventData> OnPointerUpCallBack;
            public Action<PointerEventData> OnBeginDragCallBack;
            public Action<PointerEventData> OnDragCallBack;
            public Action<PointerEventData> OnEndDragCallBack;
    
            public override void OnPointerClick(PointerEventData eventData)
            {
                if (OnPointerClickCallBack != null)
                {
                    OnPointerClickCallBack(eventData);
                }
            }
            public override void OnPointerDown(PointerEventData eventData)
            {
                if (OnPointerDownCallBack != null)
                {
                    OnPointerDownCallBack(eventData);
                }
            }
            public override void OnPointerUp(PointerEventData eventData)
            {
                if (OnPointerUpCallBack != null)
                {
                    OnPointerUpCallBack(eventData);
                }
            }
            public override void OnBeginDrag(PointerEventData eventData)
            {
                if (OnBeginDragCallBack != null)
                {
                    OnBeginDragCallBack(eventData);
                }
            }
            public override void OnDrag(PointerEventData eventData)
            {
                if (OnDragCallBack != null)
                {
                    OnDragCallBack(eventData);
                }
            }
            public override void OnEndDrag(PointerEventData eventData)
            {
                if (OnEndDragCallBack != null)
                {
                    OnEndDragCallBack(eventData);
                }
            }
        }
    }

    UIMediatorBase

    using System.Collections.Generic;
    
    namespace MyMVC
    {
        public interface IMediator
        {
            List<string> GetMessageCodes();
            void HandleMessage(IMessage msg);
        }
        public class UIMediatorBase : IMediator
        {
            public UIMediatorBase(UIBase ui)
            {
                ui.InitUI();
                Register();
            }
            public virtual void OnShow() { }
            public virtual List<string> GetMessageCodes() { return null; }
            public virtual void HandleMessage(IMessage msg) { }
            private void Register()
            {
                MessageManager.Register(this);
            }
        }
    }

    消息注册相关 MessageManager

    using System.Collections.Generic;
    
    namespace MyMVC
    {
        public class MessageManager
        {
            private static Dictionary<string, List<IMediator>> CodeMessages = new Dictionary<string, List<IMediator>>();
            private static Queue<IMessage> messagesQueue = new Queue<IMessage>();
            private static readonly int perFrameMaxMessage = 10;
            public static void Register(IMediator mediator)
            {
                List<string> codes = mediator.GetMessageCodes();
                if (codes == null)
                {
                    return;
                }
                for (int i = 0; i < codes.Count; i++)
                {
                    string code = codes[i];
                    if (!CodeMessages.ContainsKey(code))
                    {
                        CodeMessages[code] = new List<IMediator>();
                    }
                    CodeMessages[code].Add(mediator);
                }
            }
            public static void UnRegister(IMediator mediator)
            {
                foreach (var item in CodeMessages.Values)
                {
                    item.Remove(mediator);
                }
            }
            public static void SendMessage(string codeName, object body = null)
            {
                if (CodeMessages.ContainsKey(codeName))
                {
                    IMessage msg = new IMessage
                    {
                        Code = codeName,
                        Body = body
                    };
                    messagesQueue.Enqueue(msg);
                }
            }
            public static void UpdateMessages()
            {
                if (messagesQueue.Count > 0)
                {
                    for (int i = 0; i < perFrameMaxMessage; i++)
                    {
                        IMessage msg = messagesQueue.Dequeue();
                        HandleMessage(msg);
                        if (messagesQueue.Count == 0)
                        {
                            break;
                        }
                    }
                }
            }
            private static void HandleMessage(IMessage msg)
            {
                List<IMediator> mediators;
                if (CodeMessages.TryGetValue(msg.Code, out mediators))
                {
                    for (int i = 0; i < mediators.Count; i++)
                    {
                        mediators[i].HandleMessage(msg);
                    }
                }
            }
        }
    }

    消息体 IMessage

    namespace MyMVC
    {
        public class IMessage
        {
            public string Code = "";
            public object Body;
        }
    }

    UIManager 初始化 MessageManager 消息更新 相关 UITestMono

    using UnityEngine;
    
    namespace MyMVC
    {
        public class UITestMono : MonoBehaviour
        {
            private void Awake()
            {
                UIManager.Init();
                UIManager.Show<Test01UI, Test01UIMediator>();
            }
            private void Update()
            {
                MessageManager.UpdateMessages();
            }
        }
    }

    消息代码常量定义 MessageConstCodes

    namespace MyMVC
    {
        public class MessageConstCodes
        {
            public const string TheTestMessageCode = "TheTestMessageCode";
        }
    }

    应用例子说明

    using UnityEngine.UI;
    
    namespace MyMVC
    {
        public class Test01UI : UIBase
        {
            public new const string ResourcesPath = "Test01UI";
    
            private Text messageText;
            public override void InitUI()
            {
                base.InitUI();
                messageText = GetCom<Text>("Text");
            }
            public void SetText(string msg)
            {
                messageText.text = msg;
            }
        }
    }
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.EventSystems;
    
    namespace MyMVC
    {
        public class Test01UIMediator : UIMediatorBase
        {
            private Test01UI ui;
            public Test01UIMediator(UIBase ui) : base(ui)
            {
                this.ui = (Test01UI)ui;
                ui.BindButtons(this, new List<string>()
                {
                    "SendBtn",
                    "Open02UIBtn",
                });
            }
            public override void OnShow()
            {
                base.OnShow();
                Debug.Log("Test01UI show");
            }
            public override List<string> GetMessageCodes()
            {
                return new List<string>()
                {
                    MessageConstCodes.TheTestMessageCode,
                };
            }
            public override void HandleMessage(IMessage msg)
            {
                if (msg.Code.Equals(MessageConstCodes.TheTestMessageCode))
                {
                    ui.SetText(msg.Body.ToString());
                }
            }
            public void OnClickSendBtn(PointerEventData e)
            {
                MessageManager.SendMessage(MessageConstCodes.TheTestMessageCode, e.clickTime.ToString());
            }
            public void OnClickOpen02UIBtn(PointerEventData e)
            {
                UIManager.Show<Test02UI, Test02UIMediator>();
            }
        }
    }

     

    展开全文
  • Unity3D引擎目前在市场上占有了大部分游戏研发份额,由于其提供了强大的编辑器,对于初学者更容易上手,所以被越来越多的开发者所喜爱。但是在真正开发产品时,很多人喜欢用Unity3D的插件,这样做的结果是游戏产品是...

    Unity3D引擎目前在市场上占有了大部分游戏研发份额,由于其提供了强大的编辑器,对于初学者更容易上手,所以被越来越多的开发者所喜爱。但是在真正开发产品时,很多人喜欢用Unity3D的插件,这样做的结果是游戏产品是由插件堆积而成的,导致了程序模块之间的耦合性增强,不利于游戏本身的功能扩展以及游戏后期版本迭代。所以如果只是自己学习,可以使用插件快速的开发游戏,但是如果开发产品还是慎用的好,能自己动手实现的最好自己去实现,这样也容易驾驭整个产品开发。
    说到游戏开发,就不得不提游戏架构设计,一提到架构设计很多开发者对此都有点胆怯,特别是我面试了很多程序员,他们的简历上都写有会架构设计,但是提到架构设计没有一个人回答的让人满意,大部分都是答非所问。在这里就给读者普及一下架构知识,说到架构就不得不提设计模式,设计模式共有23种,这是基本常识,设计模式这本书如果从头学起来,非常抽象,不容易理解。在这里给读者一个建议,就是把游戏开发常用的设计模式:单例模式,工厂模式,抽象工厂模式,状态模式,观察者模式等这几个要重点掌握。除了提到的这几个,还有一个设计模式应用非常广泛就是MVC设计模式,它的全称:Model,View,Controller,中文意思就是模型,视图,控制器。它以前主要是应用在Web端,现在我们拿来将其应用到游戏开发中。
    MVC设计模式可以应用在UI界面切换和游戏的战斗中,下面逐一给读者介绍,MVC设计模式非常适合UI的架构,UI界面相当于View,UI转换控制相当于Controller,UI上面的数据变换相当于Model。这样一分析就很清晰了,接下来做的事情就是写代码了,在这里画一幅图帮助我们理清写代码思路:
    图片描述
    窗口之间的切换可以通过状态模式控制Controller进而控制View和Model的显示。View的设计可采用下图的思路:
    图片描述
    上图中,首先定义一个父类用于定义所有窗口的共同属性比如窗口的创建,隐藏,破坏等。子类负责具体功能实现。另外由于窗口类比较多,定义一个ViewManager管理类用于所有窗口的管理。
    接下来介绍一下MVC在战斗中的应用,我们开发过一款战斗赛车游戏,游戏中的赛车可以射击战斗,武器可以更换。我们再分析一下,武器更换可以使用View,不同武器其所带的参数是不一样的适用于Model,控制武器更换使用的是Controller。另外关于MVC设计的详细讲解在笔者出版的《Unity3D核心实战技术详解》一书中有详细讲解,并且附有代码参考学习,感兴趣的读者可以自行查看。使用MVC实现的游戏效果图如下所示:
    图片描述
    学习架构设计,关键是要掌握架构思想,在这里只是给读者举了个例子。凡事有利必有弊,读者在做产品设计时也不要一味的强求架构设计,架构设计并不适用任何产品,更不要为了架构而架构,弄巧成拙!

    最后欢迎访问IT小屋:姜雪伟个人主页

    展开全文
  • Unity3dMVC框架的使用

    2017-07-26 23:22:17
    Unity游戏的开发当中,我并没有刻意地采用MVC框架,因为不像网站开发那样,Model,View,Controller在游戏这个领域里还没有很清晰的定义。 究其原因,可能是由于不同游戏类型本身的软件架构可以相差很远,而且游戏...
  • https://blog.csdn.net/frank901/article/details/72847352 文章很简单,但我个人觉得框架逻辑上有些不合理的地方,文章中使用委托作为事件的触发,个人感觉不使用一样可以达到效果,所以没有使用委托。 大致内容...
  • 简单演示在Unity中怎么使用MVC框架思想开发
  • unity3d mvc框架

    2020-07-30 23:32:15
    unity3d mvc框架, Code Control v1.2.unitypackage,代码控制器
  • Unity3DMVC框架(一)——Strange IOC与Extension的扩展介绍 StrangeIoC框架是一个超轻量级和高度可扩展反转(IOC)框架,专门为c#和Unity编写,它是基于MVC框架扩展的。即MVCS框架。M(models),V(view),C...
  • unity基于MVC的ui框架

    2020-07-29 14:18:26
    unity基于MVC的ui框架》博客的资源,请到这里下载。自己写的框架用了几年了,也做了几个游戏,应该是经受住项目考验了吧,现在分享下简本。
  • StrangeIOC,官方的文档都不是很好理解,找到了一篇比较好的GetStart文章,顺手翻译一下,一来方便自己加深理解,二来还是想共享出来,Strange是一个unity3d中用于控制反转的第三方框架,控制反转(IOC-Inversion of ...
  • 原文:http://engineering.socialpoint.es/MVC-pattern-unity3d-ui.html 动机  和游戏开发的其他模块类似,UI一般需要通过多次迭代开发,直到用户体验近似OK。另外至关重要的是, 我们想尽快加速迭代的过程。使用...
  • MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式: Model(模型)表示应用程序核心(比如数据库记录列表)。 View(视图)显示数据(数据库记录)。 ...
  • Unity中使用MVC

    2018-05-08 11:29:07
    首先我们先谈Unity3D本身的MonoBehavior脚本。MonoBehavior我们可以将他理解为界面层与界面直接沟通的上层脚本,在他底部的控制,逻辑,数据等有必要用MonoBehavior脚本么?如果在unity中我们进行开发时如果滥用...
  • Unity MVC框架 StrangeIoC

    2019-02-25 18:41:12
    Unity MVC框架 StrangeIoC
  • 浅谈unity3d中使用MVC框架模式 MVC框架模式,相信很多人都不会陌生,数据-控制-显示分离的工作方式或者叫做代码结构会使软件(游戏)的结构清晰化,逻辑更明了。但由于MVC框架模式各部件都可以与彼此进行沟通,造成...
  • Unity3DMVC框架(二)——Strange IOC结构的介绍 StrangeIOC框架是一个超轻量级和高度可扩展反转(IOC)框架,专门为c#和Unity编写,它是基于MVC框架扩展的。即MVCS框架。M(models),V(view),C(controller),S...
  • 框架概述:做了那么久的业务开发,也做了一年多的核心战斗开发,最近想着自己倒腾一套游戏框架,当然暂不涉及核心玩法类型和战斗框架,核心战斗的设计要根据具体的游戏类型而定制,这里只是一些通用的基础系统的框架...
1 2 3 4 5 ... 20
收藏数 1,381
精华内容 552
热门标签
关键字:

unity3d框架mvc