unity自制模式(MVC与命令模式相结合)(2)

前言:

上篇《unity自制模式(MVC与命令模式相结合)(1)》已经讲述结构的说明已经源码展示,该篇就开始进行UI的实践篇。  直达上一篇(1)

一、准备:

(1)创建文件

ef3900695c4b4335ace28f65c4de3b38.png

(2)将上编文章的代码创建并放置到StaticEventScripts文件夹中

注:该文件夹中的代码不需任何编辑

e5b065bf7664414fa88aa591336f6724.png

(3)创建三个动态代码到DynamicEventScripts文件夹中

注:此文件夹中的代码是根据逻辑和面板进行随时编辑的

fde74f70e2a742fabf1ce7594926dbf0.png

附上代码:

1.CommandType是动态的,是View发给Handler所发送给Command指定的命令

public enum CommandType
{
    DEFAULT,
    DemoPanelAddModelCommand,
    DemoPanelUpdateModelCommand,
}

2.HandlerUtilities是用于注册Handler的,给Handler一个编号

public class HandlerUtilities
{
    public const ushort DemoPanelConfigHandler = 1;
}

3. UIPanelManager是程序的入口,当然你也可以编辑更好的UIPanelManager,我这里只做简单演示(里面的..Panel是下方的View层,如不理解请继续往下阅读)

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIPanelManager : MonoBehaviour
{
    public static UIPanelManager Instance;
    private void Awake()
    {
        Instance = this;
        
        DemoPanel.InitDemoPanelModel();
    }

    private void Update()
    {
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Q))
            CommandHandler.Instance.Undo(1);
        else if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.R))
            CommandHandler.Instance.Redo(1);
    }

    private DemoPanel demoPanel;
    public DemoPanel DemoPanel => demoPanel ??= new DemoPanel();
    public DemoPanelConfigArgs currentDemoPanelConfigArgs = new DemoPanelConfigArgs();
}

 二、运用:

1.unity创建UI控件 ,然后将UIPanelManager脚本随意挂载游戏对象

573d73e1a8a94249b5cfb74575495b73.png617009f960424b629d9ac92f1ebd441b.png

2.Model层:DemoPanelConfigArgs 

using UnityEngine;

/// <summary>
/// 面板的Model,需绑定相对应的Handler
/// </summary>
public class DemoPanelConfigArgs : AbsUIEventArgs
{
    public override ushort HandlerName => DemoPanelConfigHandler.Instance.HandleName;
    
    public CommandType CommandType;

    public string inputField1_Text = string.Empty;
    public string inputField2_Text = string.Empty;
    public string inputField3_Text = string.Empty;
}

3.View层:DemoPanel 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// UI面板初始化
/// </summary>
public class DemoPanel : AbsUIEvent
{
    public GameObject demoPanelObj;
    private InputField inputField1;
    private InputField inputField2;
    private InputField inputField3;
    public DemoPanel()
    {
        demoPanelObj = GameObject.Find("Canvas/DemoPanel").gameObject;
        
        inputField1 = demoPanelObj.transform.Find("InputField1").GetComponent<InputField>();
        inputField1.onEndEdit.AddListener((text) =>
        {
            DemoPanelConfigArgs demoPanelConfigArgs = new DemoPanelConfigArgs();
            demoPanelConfigArgs.inputField1_Text = text;
            demoPanelConfigArgs.inputField2_Text = inputField2.text;
            demoPanelConfigArgs.inputField3_Text = inputField3.text;
            demoPanelConfigArgs.CommandType = CommandType.DemoPanelUpdateModelCommand;
            SendEvent(demoPanelConfigArgs);
        });
        
        inputField2 = demoPanelObj.transform.Find("InputField2").GetComponent<InputField>();
        inputField2.onEndEdit.AddListener((text) =>
        {
            DemoPanelConfigArgs demoPanelConfigArgs = new DemoPanelConfigArgs();
            demoPanelConfigArgs.inputField1_Text = inputField1.text;
            demoPanelConfigArgs.inputField2_Text = text;
            demoPanelConfigArgs.inputField3_Text = inputField3.text;
            demoPanelConfigArgs.CommandType = CommandType.DemoPanelUpdateModelCommand;
            SendEvent(demoPanelConfigArgs);
        });
        
        inputField3 = demoPanelObj.transform.Find("InputField3").GetComponent<InputField>();
        inputField3.onEndEdit.AddListener((text) =>
        {
            DemoPanelConfigArgs demoPanelConfigArgs = new DemoPanelConfigArgs();
            demoPanelConfigArgs.inputField1_Text = inputField1.text;
            demoPanelConfigArgs.inputField2_Text = inputField2.text;
            demoPanelConfigArgs.inputField3_Text = text;
            demoPanelConfigArgs.CommandType = CommandType.DemoPanelUpdateModelCommand;
            SendEvent(demoPanelConfigArgs);
        });
    }

    /// <summary>
    /// 初始化面板数据
    /// </summary>
    public void InitDemoPanelModel()
    {
        DemoPanelConfigArgs demoPanelConfigArgs = new DemoPanelConfigArgs();
        demoPanelConfigArgs.inputField1_Text = "第一个输入框";
        demoPanelConfigArgs.inputField2_Text = "第二个输入框";
        demoPanelConfigArgs.inputField3_Text = "第三个输入框";
        demoPanelConfigArgs.CommandType = CommandType.DemoPanelAddModelCommand;
        SendEvent(demoPanelConfigArgs);
    }


    /// <summary>
    /// 操作面板数据
    /// </summary>
    /// <param name="demoPanelConfigArgs"></param>
    public void DemoPanelModelOperate(DemoPanelConfigArgs demoPanelConfigArgs)
    {
        inputField1.text = demoPanelConfigArgs.inputField1_Text;
        inputField2.text = demoPanelConfigArgs.inputField2_Text;
        inputField3.text = demoPanelConfigArgs.inputField3_Text;
    }
}

3. Control层:DemoPanelConfigHandler 

/// <summary>
/// 面板的Handler,将面板要处理的数据转化为命令
/// </summary>
public class DemoPanelConfigHandler : SimpleHandler<DemoPanelConfigHandler>
{
    public override ushort HandleName => HandlerUtilities.DemoPanelConfigHandler;
    public override void Dispose(IEventArgs args)
    {
        DemoPanelConfigArgs demoPanelConfigArgs = args as DemoPanelConfigArgs;
        DemoPanelCommand demoPanelCommand;
        
        
        // //命令的处理方式是一样时,可用如下写法
        // demoPanelCommand = new DemoPanelCommand(demoPanelConfigArgs);
        // CommandHandler.Instance.InsertCommand(demoPanelCommand);
        
        //针对某一命令进行处理
        switch (demoPanelConfigArgs.CommandType)
        {
            case CommandType.DemoPanelAddModelCommand:
                demoPanelCommand = new DemoPanelAddModelCommand(demoPanelConfigArgs);
                CommandHandler.Instance.InsertCommand(demoPanelCommand);
                break;
            case CommandType.DemoPanelUpdateModelCommand:
                demoPanelCommand = new DemoPanelUpdateModelCommand(demoPanelConfigArgs);
                CommandHandler.Instance.InsertCommand(demoPanelCommand);
                break;
        }
    }
}

4.Command层:DemoPanelCommand 

public class DemoPanelCommand : AbsCommand
{
    private DemoPanelConfigArgs demoPanelConfigArgs;
    
    public DemoPanelCommand() { }
    public DemoPanelCommand(DemoPanelConfigArgs currentDemoPanelConfigArgs)
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(currentDemoPanelConfigArgs);
        demoPanelConfigArgs = UIPanelManager.Instance.currentDemoPanelConfigArgs;
        UIPanelManager.Instance.currentDemoPanelConfigArgs = currentDemoPanelConfigArgs;
    }

    public override void Execute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }

    public override void UnExecute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }
}

public class DemoPanelAddModelCommand : DemoPanelCommand
{
    private DemoPanelConfigArgs demoPanelConfigArgs;
    public DemoPanelAddModelCommand(DemoPanelConfigArgs currentDemoPanelConfigArgs)
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(currentDemoPanelConfigArgs);
        demoPanelConfigArgs = UIPanelManager.Instance.currentDemoPanelConfigArgs;
        UIPanelManager.Instance.currentDemoPanelConfigArgs = currentDemoPanelConfigArgs;
    }
    
    public override void Execute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }

    public override void UnExecute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }
}

public class DemoPanelUpdateModelCommand : DemoPanelCommand
{
    private DemoPanelConfigArgs demoPanelConfigArgs;
    public DemoPanelUpdateModelCommand(DemoPanelConfigArgs currentDemoPanelConfigArgs)
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(currentDemoPanelConfigArgs);
        demoPanelConfigArgs = UIPanelManager.Instance.currentDemoPanelConfigArgs;
        UIPanelManager.Instance.currentDemoPanelConfigArgs = currentDemoPanelConfigArgs;
    }
    
    public override void Execute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }

    public override void UnExecute()
    {
        UIPanelManager.Instance.DemoPanel.DemoPanelModelOperate(demoPanelConfigArgs);
        //析构交换
        (UIPanelManager.Instance.currentDemoPanelConfigArgs, demoPanelConfigArgs) = (demoPanelConfigArgs, UIPanelManager.Instance.currentDemoPanelConfigArgs);
    }
}

三、结果演示:

1.运行unity,出现如下:

4663d9a5607c447b89792feb5eb6fa13.png

2.修改输入框数据

a12fdc33d8544cd2bdd210b6b3afde19.png

此时按下键盘的LeftCtrl+Q可以撤回修改,LeftCtrl+R可以反撤销。

四、小结

此结构,不仅适合UI面板的MVC模式,可以继续实现其他MVC模式,例如IUIEvent结构改成IEvent接口,将AbsUIEvent : IUIEvent继承改至IEvent,同时你还可以继续添加例如AbsSceneEvent : IEvent或者更多的Abs...Event : IEvent,同样也是收发消息的方式去传递Args,让Handler去指定命令去处理数据,去实现更多的MVC模式。如有不清楚的地方可观看上一篇文章   直达上一篇(1)

 

 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MVC模式(Model-View-Controller)是一种软件设计模式,主要用来组织和管理程序的开发和设计。Unity是一款游戏开发引擎,提供了一系列工具和功能来帮助开发者创建和开发游戏。 在Unity中,使用MVC模式可以将游戏的逻辑和数据组织起来,实现更好的代码结构和可维护性。具体来说,Unity中的游戏开发可以按照以下方式应用MVC模式: 1. Model(模型):模型部分是游戏中的数据和逻辑,包括角色属性、游戏状态、游戏规则等。在Unity中,我们可以使用C#编写类来表示模型,并且使用属性、方法和事件来操作和更新模型的数据。 2. View(视图):视图部分是游戏中的用户界面和展示层,包括菜单、按钮、角色模型等。在Unity中,视图可以使用GUI、UI系统或者自定义的UI组件来实现。视图负责显示模型数据,并且根据用户的操作推动控制器进行逻辑处理。 3. Controller(控制器):控制器部分是游戏中的业务逻辑,负责接收用户的输入,控制模型的更新和处理模型之间的交互。在Unity中,我们可以编写脚本来处理用户输入,并根据输入的变化来调整模型的数据或触发事件。 通过使用MVC模式Unity中的游戏开发可以更好地分离游戏的逻辑、数据和展示层,使得程序更容易理解、扩展和维护。同时,该设计模式也可以增加代码的重用性和可测试性,提高团队合作的效率。 总而言之,MVC模式Unity中的应用可以帮助开发者更好地组织游戏的逻辑和代码结构,提升开发效率和代码质量。 ### 回答2: MVC模式是一种对软件进行组织的架构模式,其中M代表模型(Model),V代表视图(View),C代表控制器(Controller)。Unity是一种跨平台的游戏开发引擎。 在Unity中使用MVC模式可以更好地管理游戏开发过程中的逻辑和界面分离。首先,模型(Model)部分负责管理游戏的数据和逻辑。它定义了游戏的规则和行为,并且可以与其他模型进行交互。在Unity中,模型可以是游戏对象的脚本,用于控制游戏对象的行为和属性。 其次,视图(View)部分负责展示游戏的界面和图形内容。在Unity中,视图可以是游戏对象的渲染组件,例如UI元素或3D模型。视图接收模型的数据并将其显示给玩家。同时,视图还可以向控制器发送用户输入的消息,以便更新游戏状态。 最后,控制器(Controller)部分是连接模型和视图的中间人。它接收视图发送的输入消息,并根据消息的类型调用模型的方法进行状态更新。控制器还可以向视图发送消息,告知其需要更新界面或显示新的内容。在Unity中,控制器可以是脚本组件,用于处理用户输入和游戏逻辑的交互。 通过使用MVC模式Unity可以实现良好的代码组织和项目管理。它将游戏逻辑,界面显示和用户交互分离开来,使开发人员可以更专注于每个部分的设计和开发。此外,MVC模式还提高了代码的可维护性和可扩展性,使团队成员可以更方便地合作开发和修改游戏。 ### 回答3: MVC(Model-View-Controller)是一种软件架构模式,用于将应用程序的不同组成部分进行分离和组织。在Unity中,也可以应用MVC模式来设计和开发游戏或应用程序。 在MVC模式中,三个主要组成部分分别为模型(Model)、视图(View)和控制器(Controller)。 1. 模型(Model):模型表示游戏或应用程序的数据和逻辑部分。它负责处理和管理数据,以及定义游戏规则和逻辑。在Unity中,模型通常是由脚本或脚本组件实现的。 2. 视图(View):视图负责展示和渲染游戏或应用程序的界面和图形。它负责将模型中的数据以可视化的形式呈现给用户。在Unity中,视图通常是由场景、UI元素或其他图形组件构成的。 3. 控制器(Controller):控制器作为模型和视图之间的桥梁,负责处理用户输入和事件,并将其转化为对模型或视图的操作。它帮助用户与游戏或应用程序进行交互,并控制游戏流程。在Unity中,控制器通常通过脚本来实现。 使用MVC模式可以提高游戏或应用程序的可维护性、可扩展性和可重用性。通过将不同的逻辑和功能进行分离,我们可以更方便地进行测试、维护和更新。 在Unity中,我们可以根据游戏或应用程序的需求,使用MVC模式来设计和实现不同的功能模块,比如角色控制、UI交互、关卡管理等。通过合理地规划和组织,我们能够更有效地编写代码、管理资源和调试错误,提高开发效率和质量。 总结:在Unity中,MVC模式可用于游戏或应用程序的设计和开发,帮助我们更好地组织和管理代码,提高软件的可维护性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平杨猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值