最终效果
前言
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
专栏推荐
完结
好了,我是向宇
,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!