Unity2021 Inventory(背包)系统学习记录
Unity2021 Inventory(背包)系统学习记录
最近学习了Unity背包系统设计的基本设计。学习资料主要参考了B站up主:M_Studio的教学视频。学习完后,在Assets Store上重新下载了一套GUI对学习到的知识进行了一次复盘。现在,对复盘的过程进行一次记录。这个背包系统主要实现了基本的背包功能,Player(玩家)在场景中拾取得到物品,然后物品能够在背包上出现,背包中的物品也能够进行移动以及交换位置。
使用的资源都是在Asset Store上下载得到的免费资源,本次使用的UI主要是GUI_Parts、Simple Fantasy GUI、Tiny RPG Forest。
1. 设置UI
- 在场景中按照以下父子关系的顺序,创建UI。
- 然后,对UI组件对象进行重新命名。
把Slot设置为预制体,Slot表示一个装备栏,装备栏里有对应的游戏物品,这个装备栏显示的是物品的图片和物品的数量。
设置好Slot预制体后,可以在游戏场景中删除Slot的UI对象。
- UI的图片可以按照自己的喜好设置,这里需要注意的是Grid对象需要添加一个Grid Layout Group组件,使Grid做成网格布局。
- 通过上述的UI组件设置,其在场景中生成的效果如下图所示。
2.设置ScriptableObject
ScriptableObject可以把数据存储在资源文件中,当退出运行时也一样会保持修改。这里把物品和背包设置成ScriptableObject对象。
新建一个C#脚本Item.cs,用于创建物体的ScriptableObject对象。
using UnityEngine;[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item")]//右键菜单快速创建 public class Item : ScriptableObject {public string itemName;//设置物品的名称public Sprite itemImage;//设置物品的图片public int itemHeld;//设置物品的数量[TextArea]public string itemInfo;//设置物品的描述public bool equip;//设置物品可否装备 }
- 新建一个C#脚本Inventory.cs,用于创建背包的ScriptableObject对象。
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Inventory", menuName = "Inventory/New Inventory")]
public class Inventory : ScriptableObject
{public List<Item> itemList = new List<Item>();//设置背包里面物品的列表
}
3.在背包UI对象添加一个InventoryManger.cs脚本,用于控制物品栏里面的物品显示。
sing System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class InventoryManger : MonoBehaviour
{private static InventoryManger instance;public Inventory myBag; // 获取背包的信息public GameObject slotGrid;//获取Grid网格对象//public Slot SlotPrefab;public GameObject emptySlot;//slot预制体public Text itemInformation;//物品描述public List<GameObject> slots = new List<GameObject>();//物品栏中的物品对象void Awake()//单例模式,保证只有一个实例{if (instance!=null){Destroy(this);}instance = this;}private void OnEnable(){RefreshItem();//每次启动程序时,刷新背包里的物品instance.itemInformation.text = "";//物品描述设置为空}public static void UpdateItemInfo(string itemDes){instance.itemInformation.text = itemDes;//设置物品描述信息}public static void RefreshItem(){//先删除物品栏中的所有游戏对象,遍历Grid挂载的子对象for (int i = 0; i < instance.slotGrid.transform.childCount; i++){if (instance.slotGrid.transform.childCount==0)//如果Grid没有挂载子对象{break;}//每遍历一个就删除一个子对象Destroy(instance.slotGrid.transform.GetChild(i).gameObject);instance.slots.Clear();}//重新加载Invetory中的物品对象。for (int j = 0; j < instance.myBag.itemList.Count; j++){instance.slots.Add(Instantiate(instance.emptySlot));instance.slots[j].transform.SetParent(instance.slotGrid.transform, false);instance.slots[j].GetComponent<Slot>().slotID = j;instance.slots[j].GetComponent<Slot>().SetupSlot(instance.myBag.itemList[j]);}}}
- 场景中的Bag物体对象,按以下组件设置。
Bag组件中的MoveBag.cs脚本主要时控制背包窗口的拖拽。
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;public class MoveBag : MonoBehaviour,IDragHandler {public Canvas canvas;private RectTransform currentRect;// Start is called before the first frame updatevoid Awake(){currentRect = GetComponent<RectTransform>();}public void OnDrag(PointerEventData eventData){currentRect.anchoredPosition += eventData.delta;} }
4.Slot预制体的设置
Slot预制体挂载一个Slot.cs脚本,这个脚本主要时控制物品的图片和物品的数量。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class Slot : MonoBehaviour {public int slotID;public Item SlotItem;public Image SlotImage;//物品图片public Text slotNum;//物品数量public GameObject itemInslot;public string slotInfo;public void ItemOnClick(){InventoryManger.UpdateItemInfo(slotInfo);//点击该物品时,物品描述将会更新}public void SetupSlot(Item item){if (item==null)//如果物品不存在,物品栏并不会激活{itemInslot.SetActive(false);return;}SlotImage.sprite = item.itemImage;slotNum.text = item.itemHeld.ToString();slotInfo = item.itemInfo;} }
Slot预制体中组件的设置如下
5.物品的拖拽
在Slot预制体中的Item物体中挂载ItemOnDrag.cs组件
using UnityEngine; using UnityEngine.EventSystems;public class ItemOnDrag : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {public Transform orignalParent;private RectTransform m_RT;public Inventory myBag;private int currentItemID;//开始拖拽public void OnBeginDrag(PointerEventData eventData){orignalParent = transform.parent;//记录物体原先的位置currentItemID = orignalParent.GetComponent<Slot>().slotID;transform.SetParent(transform.parent.parent);//把物体从父节点中分离,使其能够在最上层显示transform.position = eventData.position;GetComponent<CanvasGroup>().blocksRaycasts = false;}//拖拽public void OnDrag(PointerEventData eventData){//transform.position = eventData.position;Vector3 pos;m_RT = gameObject.GetComponent<RectTransform>();RectTransformUtility.ScreenPointToWorldPointInRectangle(m_RT,eventData.position,eventData.enterEventCamera,out pos);m_RT.position = pos;//Debug.Log(eventData.pointerCurrentRaycast.gameObject.name);}//放开拖拽public void OnEndDrag(PointerEventData eventData){//使用射线来检测物体下方是不是有物品,如果有物品则交换位置if (eventData.pointerCurrentRaycast.gameObject.name=="Item Image"){transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform.parent.parent);transform.position = eventData.pointerCurrentRaycast.gameObject.transform.parent.parent.position;//itemList的物品存储位置改变。var temp = myBag.itemList[currentItemID];myBag.itemList[currentItemID] =myBag.itemList[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID];myBag.itemList[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID] = temp;eventData.pointerCurrentRaycast.gameObject.transform.parent.position = orignalParent.position;eventData.pointerCurrentRaycast.gameObject.transform.parent.SetParent(orignalParent);GetComponent<CanvasGroup>().blocksRaycasts = true;return;}//如果放开位置没有物品,则直接放下。transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform);transform.position = eventData.pointerCurrentRaycast.gameObject.transform.position;myBag.itemList[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID] = myBag.itemList[currentItemID];myBag.itemList[currentItemID] = null;GetComponent<CanvasGroup>().blocksRaycasts = true;}}
Item物体的组件设置情况如下。
6.Player(玩家)组件的设置
Player上挂载一个PlayerMovement.cs脚本,用于控制Player的移动,以及控制背包的打开。
using System.Collections; using System.Collections.Generic; using UnityEngine;public class PlayerMovement : MonoBehaviour {Rigidbody2D rb;Collider2D coll;Animator anim;public GameObject myBag;private bool isOpen;public float speed;Vector2 movement;private void Awake(){rb = GetComponent<Rigidbody2D>();coll = GetComponent<Collider2D>();anim = GetComponent<Animator>();}private void Update(){Movement();SwitchAnim();OpenMyBag();}void Movement()//移动{movement.x = Input.GetAxisRaw("Horizontal");movement.y = Input.GetAxisRaw("Vertical");rb.MovePosition(rb.position + movement * speed * Time.deltaTime);}void SwitchAnim()//切换动画{if (movement != Vector2.zero)//保证Horizontal归0时,保留movment的值来切换idle动画的blend tree{anim.SetFloat("horizontal", movement.x);anim.SetFloat("vertical", movement.y);}anim.SetFloat("speed", movement.magnitude);//magnitude 也可以用 sqrMagnitude 具体可以参考Api 默认返回值永远>=0}void OpenMyBag(){if (Input.GetKeyDown(KeyCode.O)){myBag.SetActive(!myBag.activeSelf);}} }
7.效果演示
- 背包初始状态
- 物品转移到背包里面
- 交换物品
- 拖拽物品
Unity2021 Inventory(背包)系统学习记录相关推荐
- 【稀疏向量技术是什么?】差分隐私系统学习记录(六)
The Algorithmic Foundations of Differential Privacy (六) 写在前面的话 Remarks on composition Weak Quantific ...
- 【差分隐私入门】差分隐私系统学习记录 (一)
The Algorithmic Foundations of Differential Privacy (一) 写在前面的话 The Promise of Differential Privacy B ...
- yii验证系统学习记录,基于yiicms(一)写的太长了,再写一篇(二)
项目地址:https://gitee.com/templi/yiicms 感谢七觞酒大神的付出,和免费分享.当然也感谢yii2的开发团队们. 项目已经安全完毕,不知道后台密码,这种背景下,后台无法进去 ...
- 【线性查询之间存在相关性误差】差分隐私系统学习记录(七)
The Algorithmic Foundations of Differential Privacy (七) 写在前面的话 Releasing Linear Queries with Correla ...
- 【高斯和拉普拉斯为什么分别对应L2和L1?】差分隐私系统学习记录(五)
The Algorithmic Foundations of Differential Privacy (五) 写在前面的话 Laplace versus Gauss 什么是先验分布?后验分布?似然估 ...
- SpringBoot 微信点餐系统学习记录六-订单表和订单详情表的后端开发
在dataobject文件夹创建订单表和订单详情表的实体类 package com.imooc.dataobject;import com.imooc.enums.OrderStatusEnum; i ...
- 【差分隐私的Advanced composition到底是什么?】差分隐私系统学习记录(四)
The Algorithmic Foundations of Differential Privacy (四) 写在前面的话 Composition: some technicalities Adva ...
- 【差分隐私的指数机制该怎么理解?】差分隐私系统学习记录(三)
The Algorithmic Foundations of Differential Privacy (三) 写在前面的话 The exponential mechanism 写在前面的话 纯属个人 ...
- 【数学工具?拉普拉斯机制?随机响应?】差分隐私系统学习记录(二)
The Algorithmic Foundations of Differential Privacy (二) 写在前面的话 Basic Techniques and Composition Theo ...
最新文章
- perl学习之(not install YAML)解决
- 【原创视频教程】学生信息管理系统6--学员信息管理(完结篇)
- 【体验干货】产品经理必知:产品体验报告如何写的全而精
- postgres循环sql
- 树状数组(Binary Indexed Tree)
- eclipse juno_放弃Eclipse Juno
- 走心!北京语言大学教授毕业致辞:在人生的道路上,一定要把自己当回事儿...
- 玩转微服务日志框架Logback
- html div 水平垂直居中显示,利用CSS实现div水平垂直居中
- Python+ZeroMQ使用REQ/REP模式快速实现消息收发
- Zabbix(一)安装zabbix监控服务配置与添加agent主机的三种方式
- shell 日期格式化输出
- Android Studio躲避小球小游戏(一界面布局)
- 使用Chrome谷歌浏览器打开Axure原型图
- 求三角形外接圆圆心坐标的算法
- 【编程题 】年会抽奖(详细注释 易懂)
- RS232串口线连接方法
- 程序员的思维(转载于伯乐在线-author:水流年)
- linux dd 克隆很慢,使用dd命令进行SD卡克隆
- 亿道丨三防手机丨手持终端丨零售行业如何选择手持工业终端设备?
热门文章
- 婚礼这天你是公主,你的婚礼你做主
- 台式计算机启动时 每次按f1,开机按f1的解决方法_电脑开机每次都要按F1,怎么解决...
- vue父与子组件,子与子组件间的方法调用和通信
- C语言 键盘编码 及 用法
- what is the mes (mes系统是什么)
- 修改服务端监听器端口号为1526
- 年龄和收入对数的线性回归_金融计算收益率的时候为什么大部分用对数收益率 (Log Return) 而不是用算数收益率?...
- 一枚普通前端平淡无奇的一年 - 2021年终总结
- python opencv 读取mov文件
- 写paper之ppt画图——不定期更新