[Unity]UGUI基于MVC模式的技能装备系统
效果预览
项目分享
链接:https://pan.baidu.com/s/1azI-EPCn4zkBHwt850mstg 提取码:oem8
顺便分享一个网站 爱给网 ,里面大多数资源都可以免费下载
什么是MVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
说白了就是把模型、视图、控制分开,得到较高的可维护性和可复用性
如何应用到Unity当中
https://blog.csdn.net/yupu56/article/details/53728489
这位博主提到
”底部的控制、逻辑用什么实现好呢?方式很多,至少MVC框架模式是一个选择。而在使用MVC时,我个人认为模块内小规模使用MVC更合理,模块内的数据、控制、界面关系比较紧密,模块之间提供合理的接口进行跳转即可(不排除模块间消息沟通)。“
游戏是一个复杂的系统,局部MVC使用是非常好的选择,比如UI、AI、主角状态机,可能有时应用起来会走样,但是无论是MVC还是其他框架,目的都是分离代码逻辑,提高可维护性,目的达到即可。
项目分析
项目结构- ItemModel 属于Model层,定义了技能的结构,存储技能
- ItemView 属于View层,控制技能面板的显示效果
- MoveWithMouse 属于View层,拖拽时让图标随着鼠标移动
- ItemControl 属于Controller层,实现了技能的交换
- DragEvent 属于Controller层,触发拖拽操作,调用ItemControl
以上是技能界面涉及到的所有脚本及其功能
- AbilityView 属于View层,主界面技能栏的显示效果
- OpenCloseBox 属于控制层,打开关闭技能界面以及刷新主界面的技能栏(但并没有对数据进行更改,只是用来控制显示层)
这两个脚本是用来显示刷新主界面技能栏与打开关闭技能界面用的(数据来自于ItemModel,MVC的优点已经有些许体现)
核心思路给每一个格子一个ID,用来判断技能交换
交换核心函数
public static void SwapItem(int gridID) { ItemModel.Item temp = pickedItem; if (gridID >= ItemView.row * ItemView.col) { pickedItem = ItemModel.ability[gridID - ItemView.row * ItemView.col]; ItemModel.ability[gridID - ItemView.row * ItemView.col] = temp; } else { pickedItem = ItemModel.items[gridID]; ItemModel.items[gridID] = temp; } GameObject.Find("Bag").GetComponent<ItemView>().ShowItems(); }
通过接口IBeginDragHandler,IDragHandler,IEndDragHandler,添加拖拽函数
在拖拽开始,拖拽中,拖拽结束时调用三次SwapItem
- 第一次时,把物品放在pickedItem中,把原所在格子置为空
- 第二次,交换目标格子与pickedItem的物品
- 第三次,交换物品原所在格子与pickedItem中的物品(三次交换完成后,pickedItem仍然为null,完成了两个格子中技能的交换)
在拖拽时,被拖拽的物体跟随鼠标移动,被遮挡的对象就接受不到事件了(无法激活Drag相关的三个事件),所以我们需要添加UI事件穿透
引用雨凇MOMO大佬的帖子 http://www.xuanyusong.com/archives/3480
using UnityEngine; using System.Collections; public class UIFocus : MonoBehaviour ,ICanvasRaycastFilter { public bool IsFocus= false; public bool IsRaycastLocationValid (Vector2 sp, Camera eventCamera) { return IsFocus; } }
代码部分
这里只有技能界面涉及到的脚本,完整项目在文章开头提供了下载
- Model层
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemModel : MonoBehaviour { public class Item { public string name; public Sprite img; public Item(string name,Sprite img) { this.name = name; this.img = img; } } public static List<Item> items; public static List<Item> ability; public int size;//物品总数量,实际应在数据库中检索 Sprite[] sprites; private void Awake()//初始化数据,将精灵引用到items { items = new List<Item>(); ability = new List<Item>(); sprites = Resources.LoadAll<Sprite>("ability");//实际与数据库检索结果有关 for (int i = 0; i < ItemView.row; i++) { for(int j = 0; j < ItemView.col; j++) { items.Add(new Item("", null)); } } for(int i = 0; i < 5; i++) { ability.Add(new Item("", null)); } for(int i = 0; i < size; i++) { items[i] = new Item(" ", sprites[i]); } } }
- View层
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ItemView : MonoBehaviour { public static int row=4; public static int col=6; public GameObject grid; public Transform ability; float width; float height; private void Awake() { width = grid.GetComponent<RectTransform>().rect.width + 10; height = grid.GetComponent<RectTransform>().rect.height + 10; } //初始化,显示所有格子 private void Start() { for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { int id = j + i * col; GameObject itemGrid = Instantiate(grid, transform.position + new Vector3(j * width-col*(width-10), -i * height, 0), Quaternion.identity) as GameObject; itemGrid.transform.SetParent(transform); ShowItem(itemGrid.transform, id); itemGrid.GetComponent<ItemControl>().gridID = id;//给格子编号 } } for (int i = 0; i < 5; i++) { int id = row * col+i; GameObject itemGrid = Instantiate(grid, ability.position + new Vector3(i * width - 5 * (width - 10), 0, 0), Quaternion.identity) as GameObject; itemGrid.transform.SetParent(ability); ShowItem(itemGrid.transform, id); itemGrid.GetComponent<ItemControl>().gridID = id; } } //刷新所有格子 public void ShowItems() { for(int i = 0; i < row * col; i++) { Transform itemGrid = transform.GetChild(i); ShowItem(itemGrid, i); } for (int i = 0; i < 5; i++) { Transform itemGrid = ability.GetChild(i); ShowItem(itemGrid, row * col + i); } } //显示格子 private void ShowItem(Transform itemGrid,int id) { Image imageUGUI = itemGrid.GetChild(0).GetComponent<Image>(); if (id >= row * col) { if (ItemModel.ability[id - row * col].img!=null) { imageUGUI.color = Color.white; } else { imageUGUI.color = Color.clear; } imageUGUI.sprite = ItemModel.ability[id - row * col].img; return; } if (ItemModel.items[id].img != null) { imageUGUI.color = Color.white; }else{ imageUGUI.color = Color.clear; } imageUGUI.sprite = ItemModel.items[id].img; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class MoveWithMouse : MonoBehaviour, ICanvasRaycastFilter {//事件穿透的必要性 RectTransform rect; Image icon; // Start is called before the first frame update void Awake() { rect = GetComponent<RectTransform>(); icon = transform.GetChild(0).GetComponent<Image>(); } // Update is called once per frame void Update() { rect.position = Input.mousePosition; //如果原方框中没有图片,那么就透明显示 if (ItemControl.pickedItem != null) { if (ItemControl.pickedItem.img != null) { icon.color = Color.white; icon.sprite = ItemControl.pickedItem.img; } else { icon.color = Color.clear; } } } //忽略鼠标图标上的射线 public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) { return false; } }
- Controller层
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class DragEvent : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler { int gridID = 0;//格子编号 public static int lastID; void Start() { gridID = GetComponentInParent<ItemControl>().gridID; } //三个函数对应三个接口 public void OnBeginDrag(PointerEventData eventData) { lastID = gridID; Debug.Log(string.Format("拖动物体原所在格子:{0:D2}",lastID)); ItemControl.SwapItem(gridID); } public void OnDrag(PointerEventData eventData) { } public void OnEndDrag(PointerEventData eventData) { ItemControl.SwapItem(gridID); } }
using System.Collections; using System.Collections.Generic; using UnityEngine.EventSystems; using UnityEngine; public class ItemControl : MonoBehaviour,IDropHandler { public int gridID; public static ItemModel.Item pickedItem; // Start is called before the first frame update void Start() { pickedItem = new ItemModel.Item("", null); } public static void SwapItem(int gridID) { //第一次时,把物品放在pickedItem中,把原所在格子置为空 //第二次,交换目标格子与pickedItem的物品 //第三次,交换物品原所在格子与pickedItem中的物品(三次交换完成后,pickedItem仍然为null,完成了两个格子中技能的交换) ItemModel.Item temp = pickedItem; if (gridID >= ItemView.row * ItemView.col) { pickedItem = ItemModel.ability[gridID - ItemView.row * ItemView.col]; ItemModel.ability[gridID - ItemView.row * ItemView.col] = temp; } else { pickedItem = ItemModel.items[gridID]; ItemModel.items[gridID] = temp; } GameObject.Find("Bag").GetComponent<ItemView>().ShowItems(); } public void OnDrop(PointerEventData eventData) { Debug.Log(string.Format("拖动物体目标格子:{0:D2}", gridID)); if (gridID != DragEvent.lastID) { SwapItem(gridID); } } }
- 【Unity】基于MVC模式的双肩包系统 UGUI实现
- 【Unity】基于MVC模式的背包系统 UGUI实现
- 基于Unity3D(UGUI)的背包系统(装备系统,锻造系统,购买系统)
- 全能智能枪弹柜 基于物联网的武器装备管理系统
- 01-基于C++的简易技能系统实现
- 【Unity】基于矩阵的UGUI引导蒙版方案
- 我们的游戏世界(背包【仓库】,交易,任务,简单经济系统,装备)实现(基于仙剑demo聊聊游戏世界)第四篇谈谈背包
- 基于Unity3D(UGUI)的背包系统<四>完结篇
- 基于MVC模式的简单用户登陆注册系统demo
- OGRE+CEGUI游戏教程(5)--物品/装备和技能系统
- Unity_UGUI的事件系统
- Unity中实现弹性滚动列表基于UGUI
- Unity UGUI事件系统
- Unity基于UGUI的多行多列ListView
- 基于MVC模式的javaweb项目-网上订餐系统完整版
- 这阵子使用kbengine+unity做的游戏(mmo物品系统,装备系统,战斗系统,聊天系统完成)
- 关于李三影【Unity 游戏开发教程】装备系统 - 01. JSON数据创建与使用要做笔记的地方
- 基于Unity5.0系统的新打包方式 [第一讲]
- 【小松教你手游开发】【unity实用技能】动画系统项目实战
- 基于Unity3D(UGUI)的背包系统<二>