zoukankan      html  css  js  c++  java
  • 【Unity】基于MVC模式的背包系统 UGUI实现

    前言


    本文基于MVC模式,用UGUI初步实现了背包系统。

    Control层包括了点击和拖拽两种逻辑。


    博文首发:http://blog.csdn.net/duzixi

    下载地址:https://github.com/duzixi/InventorySystem


    一、project准备(详见project文件)

    场景中Canvas上的对象:

    • Bag:用于显示背包内容
    • PickedItem:用于显示拾取道具的图片

    资源中的预设体:

    • Item:生成背包的格子


    二、源码


    Model 层

    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    using System.Collections.Generic;
    /// <summary>
    /// 脚本功能:MVC模式——Model层。定义物品结构,保存物品数据
    /// 加入对象:Bag 背包(Canvas下的空对象)
    /// 版权声明:Copyright (c) 2015 duzixi.com  All Rights Reserved
    /// 创建日期:2015.5.8
    /// 知识要点:
    /// 1. MVC
    /// 2. 自己定义类
    /// 3. 类的嵌套
    /// </summary>
    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 int size = 16;
        Sprite[] sprites;
    
        void Awake() // 数据初始化
        {
            items = new List<Item>(); // 初始化List<Item>
            sprites = new Sprite[size];
    
            // 依据行列值初始化物品列表
            for (int i = 0; i < BagView.row; i++) {
                for (int j = 0; j < BagView.col; j++) {
                    items.Add(new Item("", null));
                }
            }
    
            // 【注意】实际开发中下面部分应由数据库取代
    		for (int i = 0; i < size; i++) {
                string name = i < 9 ?

    "0" + (i + 1) : "" + (i + 1); sprites[i] = Resources.Load(name, typeof(Sprite)) as Sprite; items[i] = new Item(" ", sprites[i]); } } }




    View 层


    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    /// <summary>
    /// 脚本功能:MVC模式 —— View视图,控制背包的显示方式
    /// 加入对象:Bag 背包 (Canvas下的空对象)
    /// 版权声明:Copyright (c) 2015 duzixi.com  All Rights Reserved
    /// 创建时间:2015.05.08
    /// 改动记录:2015.05.18 加入编号
    /// 改动记录:2015.07.03 封装显示物品行子方法
    /// 知识要点:
    /// 1. MVC
    /// 2. UGUI 
    /// </summary>
    public class BagView : MonoBehaviour {
        // 背包规格
        public static int row = 4;  // 行
        public static int col = 5;  // 列
    
        // 背包格子
        public GameObject grid;
        float width;  // 格子宽度
        float height; // 格子高度
    
        // 依据格子预设体获取宽和高
        void Awake() {
            width = grid.GetComponent<RectTransform>().rect.width;
            height = grid.GetComponent<RectTransform>().rect.height;
        }
    
    	// 初始状态:平铺格子。创建背包
    	void Start () {
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    // 计算ID值(物品列表下标)
                    int id = j + i * col;
    
                    // 实例化格子预设,按宽高布局
                    GameObject itemGrid = Instantiate(grid, transform.position + new Vector3(j * width, -i * height, 0), Quaternion.identity) as GameObject;
                    // 将实例化的格子对象设置为背包的子对象
                    itemGrid.transform.SetParent(transform);
    
    				// 调用自己定义方法:显示某个id的格子内容
    				ShowItem(itemGrid.transform, id);
    
                    // 给格子 PickUpDrop 组件编号。拾取放下时用
                    itemGrid.GetComponent<PickUpDrop>().gridID = id;
                }
            }
    	}
    
        // 又一次刷新背包显示(物品位置发生变化时)
        public void ShowItems() {
            for (int i = 0; i < row * col; i++) {
                Transform itemGrid = transform.GetChild(i);
    			ShowItem(itemGrid, i);
            }
        }
    
        // 显示物品行子
    	private void ShowItem(Transform itemGrid, int id) {
            // 显示物品名称
            Text txtUGUI = itemGrid.GetComponentInChildren<Text>();
            txtUGUI.text = ItemModel.items[id].name;
    
    		// 获取物品Icon的Image组件
    		Image imageUGUI = itemGrid.GetChild(0).GetComponent<Image>();
    		
    		// 假设有物品。就显示图片
    		if (ItemModel.items[id].img != null) {
    			imageUGUI.color = Color.white;
    		} else { // 否则不显示
    			imageUGUI.color = Color.clear;
    		}
            imageUGUI.sprite = ItemModel.items[id].img;
    	}
    }
    

    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;
    /// <summary>
    /// 脚本功能:让拾取的背包物品随鼠标移动
    /// 加入对象:PickedItem 拾取的物品
    /// 版权声明:Copyright (c) 2015 duzixi.com  All Rights Reserved
    /// 创建日期:2015.05.18
    /// 改动记录:2015.07.03 加入射线忽略
    /// 知识要点:
    /// 1. UGUI RectTransform、锚点、中心点
    /// 2. 忽略射线接口 ICanvasRaycastFilter
    /// </summary>
    
    public class MoveWithMouse : MonoBehaviour, ICanvasRaycastFilter {
        RectTransform rect; // 获取UGUI定位组件
    
    	Image icon;  // 显示当前拾取物品的图标
    
        void Awake() {
            rect = GetComponent<RectTransform>();
            // 【注意】图标对象是第0个子对象
    		icon = transform.GetChild(0).GetComponent<Image>(); 
        }
    
    	void Update () {
            // 用鼠标位置给图标图片定位
            rect.anchoredPosition3D = Input.mousePosition;
            // 依据是否有图片确定透明度
    		if (PickUpDrop.pickedItem.img != null) {
    			icon.color = Color.white;
    		} else {
    			icon.color = Color.clear;
    		}
    		icon.sprite = PickUpDrop.pickedItem.img;
    	}
    
        // 忽略鼠标图标上的射线
    	public bool IsRaycastLocationValid (Vector2 sp, Camera eventCamera) {
    		return false;
    	}
    }
    



    Control 层


    using UnityEngine;
    using UnityEngine.EventSystems;
    using System.Collections;
    /// <summary>
    /// 脚本功能:MVC模式 —— Control控制,背包内物品摆放
    /// 加入对象:Item 物品行子预设体 
    /// 版权声明:Copyright (c) 2015 duzixi.com  All Rights Reserved
    /// 创建日期:2015.05.18 duzixi.com
    /// 改动记录:2015.07.03 加入射线忽略
    /// 知识要点:
    /// 1. UGUI、MVC设计模式
    /// </summary>
    public class PickUpDrop : MonoBehaviour, IDropHandler {
        public int gridID;
    
        public static ItemModel.Item pickedItem; // 当前拾取的物品
    	
    	void Start () {
    		// 初始化当前拾取物品为空
            pickedItem = new ItemModel.Item("", null); 
    	}
    
        // 背包核心逻辑:交换
        public static void SwapItem(int gridID)
        {
            // 交换背包中的物品和拾取物品
            ItemModel.Item temp = pickedItem;
            pickedItem = ItemModel.items[gridID];
            ItemModel.items[gridID] = temp;
    
            // 刷新背包显示
            GameObject.Find("Bag").GetComponent<BagView>().ShowItems();
        }
    
    	// 当物品button被点下时(点击触发模式)
        public void Drop() {
    		SwapItem(gridID);
        }
    
        // 当物品放在格子中时(拖拽触发模式)
    	public void OnDrop (PointerEventData eventData) {
    		SwapItem(gridID);
    	}
    
    }


    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.EventSystems;
    using System.Collections;
    /// <summary>
    /// 脚本功能:MVC模式 —— Control控制。操作逻辑。拖拽事件处理
    /// 加入对象:Bag 背包 (Canvas下的空对象)
    /// 版权声明:Copyright (c) 2015 duzixi.com  All Rights Reserved
    /// 创建时间:2015.07.03
    /// 知识要点:
    /// 1. UnityEngine.EventSystem
    /// 2. IBeginDragHandlder, IDragHandler, IEndDragHander
    /// </summary>
    public class DragEvent : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {
    
    	int gridID = 0;  // 格子编号
    
    	void Start() {
    		gridID = GetComponentInParent<PickUpDrop>().gridID; // 获取格子编号
    	}
    
        // 開始拖拽
    	public void OnBeginDrag (PointerEventData eventData) {
            // 调用交换方法
    		PickUpDrop.SwapItem(gridID);
    	}
    
        // 拖拽中
    	public void OnDrag (PointerEventData eventData) {
    		// 【注意】即使没有不论什么代码处理也要实现该接口。否则拖拽不成功
    	}
        
        // 结束拖拽
    	public void OnEndDrag (PointerEventData eventData) {
            // 调用交换方法
    		PickUpDrop.SwapItem(gridID);
    	}
    	
    }
    



    后语

    眼下还有点Bug。拖拽模式下当前物体拖拽会导致物品尾随。

    另外屏幕适配还没有搞。



    
  • 相关阅读:
    注册接口
    配置node 的路由
    mongoose 与 mylab 的使用 (1)
    PHP中PDO错误/异常(PDOException)处理
    如何使用PDO查询Mysql来避免SQL注入风险?ThinkPHP 3.1中的SQL注入漏洞分析!
    PHP5中PDO的入门教程
    PHP文件夹文件拷贝/复制函数 dir_copy($src = '', $dst = '')
    php将图片以二进制保存到mysql数据库并显示
    php 显示sqlserver二进制图片
    XML文档的PHP程序查询代码
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7244624.html
Copyright © 2011-2022 走看看