首先我们下载我们的人物和背景资源,因为主要是背包系统,所以人物的移动和场景的搭建这里我们就不多讲了,我这里直接提供基础项目源码给大家去使用就行
基础项目下载地址:
链接: https://pan.baidu.com/s/1o7_RW_QQ1rrAbDzT69ApRw 提取码: 8s95
顺带说一下,这里用到了unity的几个免费
资源包,有兴趣的也可以自己去unity资源商店下载使用
人物资源:Tiny RPG-Forest
背包ui资源:SIMPLE FANTASY GUI
物品资源:Free Pixel Gear
1新建一个面板物体,命名为Bag,剧中,设置合适的宽高,我这里是500x400
2.不需要任何代码,实现按×关闭菜单界面
新建网格布局组件(Grid Layout Group)
写代码控制,如果我按下键盘tab按钮,打开和关闭背包
//背包
public GameObject myBag;
//控制背包打开关闭
bool isOpen;
//...
private void Update()
{
OpenMyBag();
}
void OpenMyBag(){
//如果我按下键盘tab按钮,打开和关闭背包
if (Input.GetKeyDown(KeyCode.Tab))
{
isOpen = !isOpen;
myBag.SetActive(isOpen);
}
}
ScriptableObject是一种本地文件存储,游戏停止运行数据不会丢失
1.新建一个Iteam代码,存储物品类,可以实例化为不同的实例,鞋子,剑,药水等
编写代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 通过以下方式控制程序集的一般信息 文件名 菜单目录名
[CreateAssetMenu(fileName = "Item", menuName = "InventroyTutorial/Item", order = 0)]
public class Item : ScriptableObject {
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 通过以下方式控制程序集的一般信息 文件名 菜单目录名
[CreateAssetMenu(fileName = "Item", menuName = "InventroyTutorial/Item", order = 0)]
public class Item : ScriptableObject {
public string itemName; // 物品名
public Sprite itemImage; //图片
public int itemNum; //数量
[TextArea]
public string itemInfo;//物品介绍
public bool isEquipment;//是否可装备
}
实例化使用实例
2.新增背包类Bag脚本,好处就是可以实例化为多个背包,比如玩家背包,铁匠铺背包,药品店背包等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Bag", menuName = "InventroyTutorial/Bag", order = 0)]
public class Bag : ScriptableObject {
public List<Item> items = new List<Item>();
}
实例化背包
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Goods : MonoBehaviour
{
//绑定实例物品类
public Item thisItem;
//绑定物品实例背包类
public Bag thisBag;
//如果碰到玩家player就把物品放到背包里
private void OnTriggerEnter2D(Collider2D other) {
if (other.gameObject.CompareTag("Player")){
AddNewItem();
//销毁物品
Destroy(gameObject);
}
}
public void AddNewItem() {
//背包是否已经包含物品
if (!thisBag.items.Contains(thisItem)){
thisBag.items.Add(thisItem);
}else{
thisItem.itemNum += 1;
}
}
}
玩家背包挂载脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerBag : MonoBehaviour
{
//哪个物品
public Item item;
//物品图片
public Image image;
//物品数量
public Text num;
}
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BagManager : MonoBehaviour
{
static BagManager instance;
//人物背包
public Bag myBag;
//背包网格
public GameObject grid;
//人物背包每个物品预设体
public PlayerBag playerBag;
//物品介绍
public Text itemInfromation;
void Awake()
{
if(instance != null) Destroy(this);
instance = this;
}
private void OnEnable() {
RefreshItem();
//默认清空描述
instance.itemInfromation.text = "";
}
//展示描述
public static void UpdateItemInfo(string itemInfo) {
instance.itemInfromation.text = itemInfo;
}
//生成背包网格物品 物品
public static void CreateNewItem(Item item){
UnityEngine.Debug.Log("生成背包网格物品");
//物品 在哪个位置生成 角度不变
PlayerBag newItem = Instantiate(instance.playerBag, instance.grid.transform.position, Quaternion.identity);
//生成
newItem.gameObject.transform.SetParent(instance.grid.transform);
//挂载数据
newItem.item = item;
newItem.image.sprite = item.itemImage;
newItem.num.text = item.itemNum.ToString();
}
//已存在物品,修改数量
public static void RefreshItem(){
//销毁背包所有的物品
for (int i = 0; i < instance.grid.transform.childCount; i++)
{
if(instance.grid.transform.childCount == 0){
break;
}
Destroy(instance.grid.transform.GetChild(i).gameObject);
}
//将我的背包列表数据生成背包网格物品
for (int i = 0; i < instance.myBag.items.Count; i++)
{
CreateNewItem(instance.myBag.items[i]);
}
}
}
物品预设体添加组件canvas group,控制拖拽物体的射线检测
实现物品的拖拽
// 导入必要的Unity库
using UnityEngine;
using UnityEngine.EventSystems;
// 定义可拖动物品的类
public class DraggableItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
// 定义物品的起始位置和拖动偏移量的变量
private Vector3 startPosition;
private Vector3 offset;
//父级
public Transform originalParent;
//eventData点击的地方 transform物体的
// 定义拖动开始时的方法
public void OnBeginDrag(PointerEventData eventData)
{
originalParent = transform.parent;
// 保存起始位置
startPosition = transform.position;
//拖动下面的会覆盖上面的问题
transform.SetParent(transform.parent.parent);
//关闭goods物体(也就是拖拽物体)的射线检测
GetComponent<CanvasGroup>().blocksRaycasts = false;
Debug.Log("拖动开始");
}
// 定义物品正在被拖动时的方法
public void OnDrag(PointerEventData eventData)
{
//跟着鼠标移动
transform.position = Input.mousePosition;
//射线检测鼠标下的物体
Debug.Log(eventData.pointerCurrentRaycast.gameObject.name);
}
// 定义拖动结束时的方法
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("拖动结束");
// 获取拖拽结束时鼠标下的物体
GameObject endObject = eventData.pointerCurrentRaycast.gameObject;
//放回原来位置
transform.position = startPosition;
GetComponent<CanvasGroup>().blocksRaycasts = true;
}
}
拖拽时,如果把物体设置到父级上,会出现物体闪烁问题优化,主要就是父级格子Grid物体上加了网格布局组件(Grid Layout Group),默认前面排列已满,物体会闪烁继续排到下面
解决:在背包物体goods预设体上加忽略布局组件(Layout Element),勾选忽略布局即可
这里我直接就给代码了,注释我写的很详细
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
// GameSaveManager类用于保存和加载背包信息
public class GameSaveManager : MonoBehaviour
{
public Inventory myInventory; // 背包信息
public void SaveGame() // 保存背包信息
{
Debug.Log(Application.persistentDataPath); // 输出保存路径
if (!Directory.Exists(Application.persistentDataPath + "/game_SaveData")) // 如果路径不存在,则创建路径
{
Directory.CreateDirectory(Application.persistentDataPath + "/game_SaveData");
}
BinaryFormatter formatter = new BinaryFormatter(); // 创建二进制转化器
FileStream file = File.Create(Application.persistentDataPath + "/game_SaveData/inventory.txt"); // 创建文件流
var json = JsonUtility.ToJson(myInventory); // 将背包信息转化为json格式
formatter.Serialize(file, json); // 将json格式的背包信息序列化到文件流中
file.Close(); // 关闭文件流
}
public void LoadGame() // 加载背包信息
{
BinaryFormatter bf = new BinaryFormatter(); // 创建二进制转化器
if (File.Exists(Application.persistentDataPath + "/game_SaveData/inventory.txt")) // 如果文件存在
{
FileStream file = File.Open(Application.persistentDataPath + "/game_SaveData/inventory.txt", FileMode.Open); // 打开文件流
JsonUtility.FromJsonOverwrite((string)bf.Deserialize(file), myInventory); // 将文件流中的背包信息反序列化到myInventory中
file.Close(); // 关闭文件流
}
}
}
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。点赞越多,更新越快哦!当然,如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~