当前位置: 首页 > news >正文

【unity实战】在unity实现一套可扩展的Model-View-Data (MVD) 系统架构设计

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 前言
    • 1、什么是MVD架构
    • 2、组件关系示意图
    • 3、Model模型和Data数据的区别
    • 4、基础文件结构设计
    • 5、游戏开发中的扩展应用
      • 5.1 可扩展卡牌系统
      • 5.2 角色系统
      • 5.3 道具/装备系统
      • 5.4 技能系统
      • 5.5 场景交互对象
      • 5.6 UI系统
  • 实例:实现一个可扩展卡牌系统
    • 1、创建MVD架构
      • 1.1 数据层 (Data)
      • 1.2 模型层 (Model)
      • 1.3 视图层 (View)
    • 2、测试调用
      • 2.1 游戏管理器脚本
      • 2.2 配置不同的卡牌模板数据
      • 2.3 创建CardView预制体
      • 2.4 配置GameManager
      • 2.5 配置按钮调用DrawCard抽卡方法方法
      • 2.6 2D场景中的 UI 和物体交互
    • 3、运行效果
  • 参考
  • 专栏推荐
  • 完结

前言

1、什么是MVD架构

Model-View-Data (MVD)是一种类似于MVC(Model-View-Controller)的架构模式,特别适合游戏开发。它将应用程序分为三个主要部分:
在这里插入图片描述

  • View: 处理游戏对象的视觉表现
  • Model: 管理游戏的核心数据和逻辑
  • Data: 存储和管理静态或配置数据

这种架构实现了

  • 数据与逻辑分离

  • 状态与表现分离

  • 支持灵活的实例化

  • 便于扩展和维护

2、组件关系示意图

在这里插入图片描述

3、Model模型和Data数据的区别

在这里插入图片描述
虽然模型和数据看起来很相似,但还是有一些差异。

  • 数据是静态模板(每个类型只有一份)
  • 模型是动态实例(可根据数据创建多个)

示例说明,以"史莱姆卡牌"为例:
在这里插入图片描述

  • 数据层定义

    • 基础攻击力:5

    • 基础生命值:10

    • 初始效果:治疗+2

  • 游戏运行时

    • 可以创建多个史莱姆卡牌实例

    • 每个实例继承数据层的初始值

    • 各实例的状态可独立变化(如一个生命值提升为11,另一个仍保持7)

    • 视图实时显示每个实例的当前状态

4、基础文件结构设计

Assets/
├── Scripts/
│ ├── Core/
│ │ ├── Models/ // 模型层
│ │ ├── Views/ // 视图层
│ │ ├── Data/ // 数据层
│ ├── Utilities/ // 工具类
│ └── GameManager.cs // 游戏入口

5、游戏开发中的扩展应用

5.1 可扩展卡牌系统

  • 数据层:存储基础属性(名称/图标/基础数值)、定义卡牌效果模板、提供卡牌生成蓝图
  • 模型层:维护卡牌当前属性(攻击力/生命值等)、管理临时状态和效果(增益/减益)、执行游戏逻辑运算
  • 视图层:显示卡牌的实时状态和数据、处理玩家交互(点击/拖拽等)、播放视觉特效和动画

5.2 角色系统

  • 数据层:角色基础属性(血量/攻击力)、技能模板
  • 模型层:实时状态(当前血量/装备加成)、Buff/Debuff
  • 视图层:3D模型、血条UI、技能特效

5.3 道具/装备系统

  • 数据层:武器基础伤害、耐久度、图标
  • 模型层:当前耐久度、强化等级、附魔效果
  • 视图层:背包图标、装备外观、粒子特效

5.4 技能系统

  • 数据层:技能CD、伤害公式、动画触发参数
  • 模型层:当前冷却时间、连击计数
  • 视图层:技能图标、施法特效、屏幕震动

5.5 场景交互对象

  • 数据层:可破坏物件的抗性参数
  • 模型层:当前耐久值、破坏状态
  • 视图层:裂纹贴图、破碎动画

5.6 UI系统

  • 数据层:窗口布局配置、文字内容
  • 模型层:打开/关闭状态、动态数据绑定
  • 视图层:实际渲染的UI元素

实例:实现一个可扩展卡牌系统

1、创建MVD架构

1.1 数据层 (Data)

using UnityEngine;//存储卡牌数据
[CreateAssetMenu(menuName = "Card Data")]
public class CardData : ScriptableObject 
{[field: SerializeField] public Sprite Sprite { get; private set; } // 卡牌图片[field: SerializeField] public int Cost { get; private set; }      // 卡牌费用[field: SerializeField, TextArea] public string Effect { get; private set; }  // 卡牌效果描述
}
  • 功能:卡牌原始定义库

  • 职责:

    • 存储基础属性(名称/图标/基础数值)

    • 定义卡牌效果模板

    • 提供卡牌生成蓝图

  • 特性:

    • 使用ScriptableObject实现

    • 只读设计(运行时不可修改)

    • 单数据可生成多实例

1.2 模型层 (Model)

using UnityEngine;public class Card
{private readonly CardData cardData; // 只读的卡牌基础数据// 构造函数:用CardData初始化卡牌public Card(CardData cardData){this.cardData = cardData;Effect = cardData.Effect; // 初始化效果Cost = cardData.Cost;    // 初始化费用}// 属性public Sprite Sprite => cardData.Sprite; // 获取卡牌图片(简写属性)public string Title => cardData.name;    // 卡牌标题使用ScriptableObject的名称public int Cost { get; set; }           // 卡牌费用(可修改)public string Effect { get; set; }      // 卡牌效果(可修改)// 执行卡牌效果public void PerformEffect(){Debug.Log($"触发卡牌效果:{Effect},费用:${Cost}");// 这里可以扩展实际游戏效果逻辑}
}
  • 功能:卡牌运行时动态状态容器

  • 职责:

    • 维护卡牌当前属性(攻击力/生命值等)

    • 管理临时状态和效果(增益/减益)

    • 执行游戏逻辑运算

  • 特性:

    • 基于数据层实例化

    • 支持运行时状态修改

    • 每个卡牌实例拥有独立模型

1.3 视图层 (View)

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;public class CardView : MonoBehaviour, IPointerClickHandler // 实现点击接口
{[SerializeField] private SpriteRenderer cardImage; // 卡牌图片渲染器[SerializeField] private TMP_Text title;         // 卡牌标题文本(TextMeshPro)[SerializeField] private TMP_Text cost;          // 卡牌费用文本(TextMeshPro)[SerializeField] private TMP_Text effect;          // 卡牌效果描述文本(TextMeshPro)private Card card; // 关联的卡牌逻辑对象// 初始化卡牌视图public void Setup(Card card){this.card = card;cardImage.sprite = card.Sprite; // 设置卡牌图片title.text = card.Title;        // 设置标题cost.text = card.Cost.ToString(); // 设置费用effect.text = card.Effect;  //设置卡牌效果描述}// 点击卡牌时的处理public void OnPointerClick(PointerEventData eventData){card.PerformEffect(); // 执行卡牌效果Destroy(gameObject);  // 使用后销毁卡牌(可根据需求修改)}
}
  • 功能:卡牌在游戏世界中的可视化表现

  • 职责:

    • 显示卡牌的实时状态和数据

    • 处理玩家交互(点击/拖拽等)

    • 播放视觉特效和动画

  • 特性:纯表现层,不存储业务逻辑

2、测试调用

2.1 游戏管理器脚本

这里我们创建一个小型的游戏管理器脚本,以便我们可以测试调用前面创建的MVD架构

using System.Collections.Generic;
using UnityEngine;public class GameManager : MonoBehaviour
{[SerializeField] private List<CardData> cardDatas; // 所有卡牌数据列表[SerializeField] private CardView cardView;       // 卡牌视图预制体private List<Card> deck; // 卡组private void Start(){InitializeDeck(); // 初始化卡组}// 初始化卡组(创建10张随机卡牌)private void InitializeDeck(){deck = new List<Card>();for (int i = 0; i < 10; i++){// 随机选择卡牌数据CardData data = cardDatas[Random.Range(0, cardDatas.Count)];// 创建新卡牌并加入卡组Card card = new Card(data);deck.Add(card);}}// 抽卡方法public void DrawCard(){if (deck.Count == 0) return; // 卡组为空时不抽卡// 随机选择一张卡Card drawnCard = deck[Random.Range(0, deck.Count)];deck.Remove(drawnCard); // 从卡组移除// 实例化卡牌视图CardView view = Instantiate(cardView);view.Setup(drawnCard); // 初始化卡牌视图}
}

2.2 配置不同的卡牌模板数据

在这里插入图片描述

2.3 创建CardView预制体

在这里插入图片描述

2.4 配置GameManager

在这里插入图片描述

2.5 配置按钮调用DrawCard抽卡方法方法

在这里插入图片描述

2.6 2D场景中的 UI 和物体交互

注意,前面CardView代码里我们使用EventSystem 系统的IPointerClickHandler接口的OnPointerClick方法实现点击卡牌时触发卡牌效果。要使用它处理 2D 场景中的 UI 和物体交互,我们还需要注意下面的准备:

  • 确保物体上有Collider2D组件

  • 场景中需要有EventSystem对象(新建UI时会自动创建)

  • 主相机需要有Physics2DRaycaster组件

3、运行效果

在这里插入图片描述

参考

https://www.youtube.com/@thecodeotter


专栏推荐

地址
【unity游戏开发入门到精通——C#篇】
【unity游戏开发入门到精通——unity通用篇】
【unity游戏开发入门到精通——unity3D篇】
【unity游戏开发入门到精通——unity2D篇】
【unity实战】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架/工具集开发】
【unity游戏开发——模型篇】
【unity游戏开发——InputSystem】
【unity游戏开发——Animator动画】
【unity游戏开发——UGUI】
【unity游戏开发——联网篇】
【unity游戏开发——优化篇】
【unity游戏开发——shader篇】
【unity游戏开发——编辑器扩展】
【unity游戏开发——热更新】
【unity游戏开发——网络】

完结

好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
在这里插入图片描述

http://www.dtcms.com/a/329608.html

相关文章:

  • 常用 MaxKB 函数库(HTTP、MYSQL)
  • Qt中实现OpenGL应用的编程框架
  • [系统架构]系统架构基础知识(一)
  • 面向局部遮挡场景的目标检测系统设计与实现
  • 打造专属 React 脚手架:从 0 到 1 开发 CLI 工具
  • 万字详解C++11列表初始化与移动语义
  • Mysql——》提取JSON对象和数组
  • 微信小程序使用高德api实现导航至目的地
  • 【完整源码+数据集+部署教程】武器目标检测系统源码和数据集:改进yolo11-AggregatedAtt
  • Ansible 实操笔记:Playbook 与变量管理
  • 智驾系统架构解析
  • 深入解析Go设计模式:命令模式实战
  • 在verdi中查看波形中的glitch
  • 数字货币的去中心化:重构价值交换的底层逻辑​
  • 认识下windows下的设备管理器
  • 算法题打卡力扣第11题:盛最多水的容器(mid)
  • TF-IDF实战——《红楼梦》文本分析
  • 深度学习(5):激活函数
  • 敏感数据目录是什么?如何快速构建企业自身的敏感数据目录
  • flex-wrap子元素是否换行
  • Linux:磁盘管理
  • 使用HtmlAgilityPack+PuppeteerSharp+iText7抓取Selenium帮助文档
  • 学习嵌入式的第十九天——Linux——文件编程
  • 【MyBatis批量更新实现】按照list传入批量更新
  • java中数组和list的区别是什么?
  • 如何生成.patch?
  • 旧版MinIO的安装(windows)、Spring Boot 后端集成 MinIO 实现文件存储(超详细,带图文)
  • Spring Boot 3 连接池最大连接数设置建议
  • HTTP 协议详细介绍
  • Spring事务管理实战:从注解到进阶