UGUI实现背包系统

2023-11-10

一、项目需求:

1、可以生成物品

2、提示物品相关信息

3、能拖拽背包中的物品进行交换、丢弃操作

 

二、实现步骤:

1,背包中的物品包括各种种类,如武器、消耗品、防具等,它们具备一些相同的属性,如ID、名字、描述、购买价格、出售价格、图标等,同时需要一个字段用于标志这个物品到底是什么类型的(让子类进行修改,最好的类型是枚举,这里我使用的是字符串),于是很容易想到建立一个基类Item:

public class Item 
{
    public int ID { get; private set; }
    public int Num { get; private set; }
    public string Name { get; private set; }
    public string Description { get; private set; }
    public int BuyPrice { get; private set; }
    public int SellPrice { get; private set; }
    public string Icon { get; private set; }
    public string ItemType { get; protected set; }

    public Item(int id, int num, string name, string description,
        int buyPrice, int sellPrice, string icon)
    {
        this.ID = id; this.Num = num; this.Name = name; this.Description = description;
        this.BuyPrice = buyPrice; this.SellPrice = sellPrice; this.Icon = icon;
    }
}

同时衍生出其他所需要的物品类型,武器类需要攻击力的字段、消耗品类需要回复Hp、Mp数值的字段、防具需要力量、防御和敏捷的字段:

武器类:

public class Weapon : Item
{
    public int Damage {get;private set;}
    public Weapon(int id, int num, string name, string description,
        int buyPrice, int sellPrice, string icon, int damage)
        : base(id, num, name, description, buyPrice, sellPrice, icon)
    {
        this.Damage = damage;
        base.ItemType = "Weapon";
    }
}

消耗品类:

public class Consumable : Item
{
    public int BackHp { get; private set; }
    public int BackMp { get; private set; }
    public Consumable(int id, int num, string name, string description,
        int buyPrice, int sellPrice, string icon, int backHp, int backMp)
        : base(id, num, name, description, buyPrice, sellPrice, icon)
    {
        this.BackHp = backHp;
        this.BackMp = backMp;
        base.ItemType = "Consumable";
    }
}

防具类:

public class Armor : Item
{
    public int Power { get; private set; }
    public int Defend { get; private set; }
    public int Agility { get; private set; }
    public Armor(int id, int num, string name, string description,
        int buyPrice, int sellPrice, string icon, int power, int defend, int agility) :
        base(id, num, name, description, buyPrice, sellPrice, icon)
    {
        this.Power = power;
        this.Defend = defend;
        this.Agility = agility;
        base.ItemType = "Armor";
    }
}

 

2、制作背包系统的UI:

创建格子UI:

在Canvas下创建一个GridPanel作为背包的大背景,在GridPanel下创建格子背景GridBg,背景下放格子Grid,将格子作为预制体,给GridPanel添加一个组件GridLayoutGroup,根据需要修改Padding下的CellSize和Spacing属性,给GridPanel添加一个脚本GridPanelUI,用这个脚本来管理所有的格子,因为当需要生成物品时,我们需要知道背包中的空格子,在这个脚本中获取一个空格子。

 

创建物品UI:创建一个空物体Item,创建子物体包括Image(物品图片)和Text(数量),给Item添加脚本ItemUI,用于动态加载格子的内容,因为生成物品是随机的,会产生不同的物品。

 

3、如何得到物品的数据,于是我们需要另一个类KnapsackManager,其中包含一个字典public Dictionary<int, Item> ItemList;用于保存这些数据,编写一个Load方法,通过1中的类实例化一个个对象,再将对象保存到这个字典中即可,除此之外,还需要一个保存物品的方法,即:生成一个物品,将物品放到一个空格子下,注意:考虑到后来交换物品的操作,我们需要建立起格子和物品的对应关系,所以还需要一个类ItemModel处理这些数据(包括添加、查找、删除)

 public void StoreItem(int itemId)
 {
        if (!ItemList.ContainsKey(itemId))
        {
            return;
        }
        Transform emptyGrid = GridPanelUI.GetEmptyGrid();
        if (emptyGrid == null)
        {
            Debug.LogWarning("背包已满!");
            return;
        }
        Item temp = ItemList[itemId];
        CreateNewItem(temp, emptyGrid);
}

private void CreateNewItem(Item item, Transform parent)
{
        GameObject itemPrefab = Resources.Load<GameObject>("Prefabs/Item");
        ItemUI itemUI = itemPrefab.GetComponent<ItemUI>();
        Sprite s = Resources.Load<Sprite>("Image/" + item.Icon);

        itemUI.UpdateItemImg(s);
        itemUI.UpdateItemNum(item.Num);
        GameObject.Instantiate(itemPrefab, parent);

        ItemModel.StoreItem(parent.name, item);//注意不要忘了每创建一个数据就要建立起格子和物品的对应关系
 }

 

而在ItemModel中(具体代码不加以赘述):

public class ItemModel
{
    private static Dictionary<string, Item> m_GridItem = new Dictionary<string, Item>();
    public static void StoreItem(string name, Item item)
    {
    }
    public static Item GetItem(string name)
    {
    }
    public static void DeleteItem(string name)
    {
    } 
}

 

4、如何产生物品,这里我们采用鼠标右键单击的方式模拟:

创建一个类InputDetector:

 void Update()
 {
        if (Input.GetMouseButtonDown(1))
        {
            int index = Random.Range(0, 10);
            KnapsackManager.Instance.StoreItem(index);
        }
 }

 

5、实现当鼠标移动到物品上时,会弹出一个提示框,制作一个提示框(注意ContentSizeFitter的使用),为提示框添加脚本TooltipUI:主要包括更新文本内容、显示、隐藏、跟随鼠标的功能

为格子创建一个GridUI脚本用于鼠标事件监测(鼠标进入、鼠标移出):

实现IPointerEnterHandler, IPointerExitHandler接口,暴露出对应的事件:

public static Action<Transform> OnEnter;
public static Action OnExit;

让KnapsackManager来监听:

当鼠标进入格子的时候就让TooltipUI显示并更新内容,当移出格子的时候就让TooltipUI隐藏起来

至于提示框的跟随则在Update中进行检测即可,但要注意屏幕坐标和世界坐标的转换

 

6、拖拽功能的实现与提示框的实现大体一致,只是实现的接口是

IBeginDragHandler,IDragHandler,IEndDragHandler,另外值得注意的是这两个事件携带的参数:

public static Action<Transform> OnLeftBeginDrag;
public static Action<Transform, Transform> OnLeftEndDrag;

当开始拖拽时传入的是当前鼠标下面的格子,将格子中的数据传递给DragItemUI,同时删除视图中的游戏物体

Destroy(gridTransform.GetChild(0).gameObject);

让DragItem跟随鼠标移动

而当拖拽结束时传入的两个参数,一个是当前拖拽的格子,一个是鼠标下面的游戏物体

 

当结束拖拽时分为以下几种情况:

当鼠标下方的transform为空,意为拖到了背包外面,想要丢弃物品,那么在ItemModel中删除拖拽的物品

当鼠标下方的物体为格子,又分为两种情况,一,格子下面没有物品,那么在ItemModel中删除拖拽的物品,重新建立格子和物品的对应关系,二,格子下面有物品,交换两个格子的物品,听起来似乎有些复杂,但实际上只需要分别得到两个格子,重新建立关系即可,注意要删除视图中的进入格子的物品

其他情况,则是在背包中,但有没有拖拽到格子上,则将物品返回到原处

 if (enterTransform == null)
 {
            ItemModel.DeleteItem(prevTransform.name);
            Debug.LogWarning("物品已扔");
 }
else if (enterTransform.tag == "Grid")
 {
            if (enterTransform.childCount == 0)
            {
                Item item = ItemModel.GetItem(prevTransform.name);
                if (item == null)
                    return;
                ItemModel.DeleteItem(prevTransform.name);
                CreateNewItem(item, enterTransform);              
            }
            else
            {
                Destroy(enterTransform.GetChild(0).gameObject);
                Item prevGridItem = ItemModel.GetItem(prevTransform.name);
                Item enterGridItem = ItemModel.GetItem(enterTransform.name);
                CreateNewItem(prevGridItem, enterTransform);
                CreateNewItem(enterGridItem, prevTransform);
            }
 }
else
{
            Item item = ItemModel.GetItem(prevTransform.name);          
            CreateNewItem(item, prevTransform);
 }

 

三、重难点及遇到的问题:

1、物品之间的继承关系

2、用两个字典保存数据,一个是id与item对应的字典(模板数据),一个是格子与物品对应的字典(实例数据)

3、结束拖拽时的逻辑

遇到的问题:

当结束拖拽时鼠标下方为格子,而格子下没有游戏物体时具体又分为两种情况:

1、此格子为之前格子所在位置

2、此格子不为之前格子所在位置

看下面这段代码,如果是情况2没有问题,但如果是情况1呢?

if (enterTransform.childCount == 0)
{

   Item item = ItemModel.GetItem(prevTransform.name);
   if (item == null)
                    return;

  CreateNewItem(item, enterTransform);      
   ItemModel.DeleteItem(prevTransform.name);       

}

 

四、实现效果:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UGUI实现背包系统 的相关文章

  • unity中通过touch旋转、放大和缩小物体以及滑动方向的判断

    unity中通过touch旋转 放大和缩小物体以及滑动方向的判断这个需求在游戏开发中也是非常频繁 话不多说直接上代码 using System Collections using System Collections Generic usi
  • Unity3D射线检测

    射线检测主要用于像子弹是否打中物体 捡取物品等情况 本来面向百度想找例子看看 不过没找到合适的 还是自己总结尝试吧 以下测试Unity3D版本 2017 4 2f2 射线的检测步骤如下 1 Ray 这个类为了产生一个射线 如果我们想要场景中
  • unity3d实现简单的打飞碟游戏

    游戏内容 游戏有n个round 每个round发射10次trial 每个trial的飞碟都可能不同 包括速度角度得分等 使用鼠标进行射击 点中即表示射击成功 游戏要求 使用带缓存的工厂模式来管理飞碟的生产与再利用 工厂使用单例模式 游戏的设
  • Unity笔记:修改代码执行的默认打开方式

    使用 External Tools 偏好设置可设置用于编写脚本 处理图像和进行源代码控制的外部应用程序 External Script Editor 选择 Unity 应使用哪个应用程序来打开脚本文件 Unity 会自动将正确的参数传递给内
  • Unity编辑器扩展——进度条显示通用方法

    在我们使用Unity编辑器扩展做一些批处理的工具时 通常会需要显示一个进度条 这样不会让Unity一直卡住不动 使得使用者不知道当前的进展 那么如何显示进度条呢 涉及的相关API有 EditorUtility ClearProgressBa
  • JPush极光推送Unity插件iOS设备无法获取DeviceToken

    前言 最近在使用JPush进行极光推送 Unity插件GitHub地址https github com jpush jpush unity3d plugin 问题描述 但是发现了一个问题 按照官方文档操作 最终仍然无法获取DeviceTok
  • 【Unity-学习-021】异步实现HTTP请求

    对Http访问操作 Unity中一般使用协程操作 但是协程有一个比较要命的要求就是所在Mono必须在场景中是激活的 所以一些操作就会被限制 所以我们就找办法替代掉协程做一些异步的操作 那就用异步方法 首先扩展一下AsyncOperation
  • unity 读取和写入Excel中文出现乱码解决方法

    在编辑器中读取和写入中文一切正常 发布出来只要是中文就会出现乱码 解决方法 将C Program Files Unity Editor Data Mono lib mono unity 目录下的I18N dll和I18N CJK dll复制
  • unity本地分数排行榜简单解决方案(Json)

    具体效果 大体方法 创建一个分数类Score和一个分数类的容器List
  • Unity_如何使相机视角一直跟随角色移动

    实例代码如下 using System Collections using System Collections Generic using UnityEngine 相机视角跟踪 public class FollowTarget Mono
  • Unity里清除Console控制台Log的函数

    Log输出部分转发来自 http blog sina com cn s blog 13c4bf4b40102wz0r html 在控制台输出中 是开发者常用到的一种函数 通过Debug类来实现 打印字符串 Debug Log log 如果有
  • Unity3D Engine Architecture

    原文 http www umingo de doku php id paper mechs and tanks section03 Architecture To better understand the game s software
  • unity粒子特效附上贴图后播放动画

    转自 http jingyan baidu com article f96699bbb1a0d6894f3c1b77 html 参考 http www unitymanual com thread 2993 1 1 html dsign a
  • Unity3D 官方文档 平台特殊化之Standalone和多显示器的处理

    版本 unity 5 6 语言 C 总起 Standalone 我一眼看下去的理解就是PC机平台 官方文档中说该平台指的是Mac Windows和Linux 这篇文章主要讲的是Standalone平台下的设置 通过点击菜单栏的File gt
  • Unity使用spine动画

    Unity使用spine动画 在 Unity 中 常常使用 Spine 来制作一些动画 引擎本身并不能直接播放 Spine 动画 需要额外导入一个 RunTime 插件库才能支持 官网插件导入 当然 也可以到 Spine 官网关于 Unit
  • Unity中UI框架的使用1-添加面板、显示Loading页面

    其中BasePanel和Canvas都是挂在面板的预制物上的 1 导入我们的UI框架 本篇文章中有用的是两个UIPanelType NUIManager和NBasePanel 会放在文章最后供大家使用 2 先将我们做好的Panel设置成预制
  • Unity中UI组件

    一 Canvers 画布组件 Canvers下面是添加Button和Image组件 Rect Transform 1 Position 坐标位置 2 Width Height 高宽尺寸 3 Anchors 锚点 4 Pivot中心点 即UI
  • Mecanim Any State

    Any State表示任意状态 任意状态是 一个一直存在的特殊状态 他的存在是为了保证你在无意转移至某个你当前正处于的特殊状态而准备的 为你的状态机中的每个状态设置相同的对外转移是一个快捷的方式 假如有Walk Run Fly Die这四个
  • Unity3D的四种坐标系

    1 World Space 世界坐标 我们在场景中添加物体 如 Cube 他们都是以世界坐标显示在场景中的 transform position可以获得该位置坐标 2 Screen Space 屏幕坐标 以像素来定义的 以屏幕的左下角为 0
  • Unity3d中脚本无法编译问题(Monodevelop)

    使用Monodevelop打开脚本 编译时报错 具体错误忘记了 原因是 net框架引起 升级到 net框架4 5后解决

随机推荐

  • 使用jQuery实现显示文字气球的提示

    使用jQuery实现显示文字气球的提示 本文由 arthinking 发表于884 天前 Javascript 暂无评论 被围观 3 115 views 为了使页面效果更绚丽 可以使用文字气球的提示功能 在jQuery中 可以使用简单的几条
  • Unity Mecanim动画系统 之 解决模型有些动画播放后发生的位置、方向偏转 (根骨骼动画)的问题

    Unity Mecanim动画系统 之 解决模型有些动画播放后发生的位置 方向偏转 根骨骼动画 的问题 目录 Unity Mecanim动画系统 之 解决模型有些动画播放后发生的位置 方向偏转 的问题 一 简单介绍 二 实现原理 三 效果预
  • ebay运营思路

    Ebay是一个老牌的跨境电商 目前仍然是稳坐全球前列的平台 也是强手如云的地方 虽然相对于亚马逊他显得没有那么 卷 要在这片市场中抢占一番天地 首先一定要学会一些高效的运营技巧 今天就来分享一些Ebay运营技巧 帮助你更快更好的打造一个高质
  • STM32四旋翼设计——1.系统架构

    一 前言 历时一年半 终于将STM32四旋翼调通 2023 4 9顺利起飞 现在想将这个设计过程都记录下来 包括板子的设计方案 板卡结构设计 板卡原理图 PCB 各模块调试的过程 但大部分只涉及硬件 软件部分后面看情况整理 因为程序部分我也
  • 用vite 新建vue3项目

    1 component里的HelloWorld vue 是组件 2 总的vue App vue 3 index css 写的App vue的css 不是组建的vue 为什么呢 4 main js 几个import来源 HelloWorld
  • 694 不同岛屿的数量

    题目描述 给定一个非空 01 二维数组表示的网格 一个岛屿由四连通 上 下 左 右四个方向 的 1 组成 你可以认为网格的四周被海水包围 请你计算这个网格中共有多少个形状不同的岛屿 两个岛屿被认为是相同的 当且仅当一个岛屿可以通过平移变换
  • IOS本地推送 学习手记

    iOS上有两种消息通知 一种是本地消息 Local Notification 一种是远程消息 Push Notification 也叫Remote Notification 设计这两种通知的目的都是为了提醒用户 现在有些什么新鲜的事情发生了
  • JavaWeb学习笔记 ---- HTML

    web概念概述 软件架构 1 C S Client Server 客户端 服务器端 在用户本地有一个客户端程序 在远程有一个服务器端程序 优点 用户体验好 缺点 开发 安装 部署 维护 麻烦 2 B S Browser Server 浏览器
  • Python机器学习从零开始(一)序章

    目录 前言 写在前面 1 什么是机器学习 1 1 监督学习 1 2无监督学习 2 Python中的机器学习 3 必须环境安装 Anacodna安装 总结 前言 每一次变革都由技术驱动 纵观人类历史 上古时代 人类从采集狩猎社会 进化为农业社
  • node.js学习笔记--定义GET和POST路由

    const http require http const queryString require querystring const server http createServer req res gt const url req ur
  • csapp 第一章 计算机系统漫游

    计算机系统由硬件和系统软件组成 共同工作来运行应用程序 include
  • Java基础+进阶

    本文适合Java入门和复习回顾 高级篇请参考导航里的面试题 导航 黑马Java笔记 踩坑汇总 Java基础 JavaWeb SSM SpringBoot 瑞吉外卖 SpringCloud 黑马旅游 谷粒商城 学成在线 牛客面试题 目录 一
  • 实现小说分页article

    翻页过程 代码实现 css部分 margin 0 padding 0 box sizing border box wrapper height 100vh overflow hidden margin 0 16px article colu
  • 【每日知识】React学习笔记

    一 React特点 1 声明式编程 2 组件化开发 3 多平台适配 二 React开发依赖 1 React 包含react所必须的核心代码 2 react dom react渲染在不同平台所需的核心代码 3 babel 将jsx转换成rea
  • 【ChatGPT实战】9.使用ChatGPT-+-Midjourney-帮忙做了个App

    在当今数字化的时代 手机App已经成为人们生活的重要组成部分 开发一个优秀的手机App需要付出大量的时间和精力 特别是在设计和开发阶段 但是现在我们可以借助工具和技术来协助自己简化这个过程 在这篇教程中 我将介绍如何使用ChatGPT和Mi
  • 类模板以及赋值运算符重载、拷贝构造函数

    编译器默认的拷贝构造函数 是发生的浅拷贝 像指针的赋值就会让指针指向同一个地址空间 析构时就会对同一个地址空间释放两次 就会造成程序崩溃 自定义在模板内的拷贝构造函数 Queue const Queue
  • Mysql数据库笔记

    Mysql数据库 1 初识数据库 1 解决数据读取慢的问题 2 数据一致性 3 数据的安全性 4 解决了并发问题 数据库管理系统DBMS 数据库管理员DBA 数据库database db 表 table 数据库分类 1 关系型数据库 数据之
  • 数据库基础知识整理文档

    Oracle数据库基本数据类型 分类 数据类型 存储内容 存储空间 备注 数值 Number 数值 22个字节 number n 只能存储整数 精度n来指定 number n m 存储小数 n 代表整数位数 小数位数 m代表的小数位数 整数
  • C++ lambda自定义map,set,vector,list 排序规则

    Map和Set本质红黑二叉树 插入数据时可以自定义比较算法 list和vector链表插入时无需比较 所以一般全部插入完成后调用sort 核心代码 typedef struct MyStudent std string name int g
  • UGUI实现背包系统

    一 项目需求 1 可以生成物品 2 提示物品相关信息 3 能拖拽背包中的物品进行交换 丢弃操作 二 实现步骤 1 背包中的物品包括各种种类 如武器 消耗品 防具等 它们具备一些相同的属性 如ID 名字 描述 购买价格 出售价格 图标等 同时