使用Json实现背包系统的数据存储(二)
一、美术准备(做个斧头)
在blender里面做个斧头作为需要捡起来的物体。
这里放进去发现贴图颜色略有变化,我这里使用的是URP,不清楚原因,还请大家指教,有解决办法万分感谢。
二、Json数据与GUI界面连接起来
我们需要每次吃到斧头后,将斧头的数据放入到背包中(背包类的List列表)
所以我们需要一个ItemOnWorld,即世界物体与背包数据的交互
public class ItemOnWorld : MonoBehaviour
{
[Header("物体所属的背包")]
public BagManager Bag;
private Item item=new Item();
[Header("物体属性")]
public string name;
public int number;
public string des;
public string type;
public string spritePath;
private void Awake()//将属性赋予物体
{
item.name = name;
item.number = number;
item.des = des;
item.type = type;
item.spritePath = spritePath;
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
{
AddNewItem();
Destroy(this.gameObject);
}
}
private void AddNewItem()
{
foreach (var m_item in Bag.Mydata.bagData)//检测有没有同名物体,没有就添加
{
if (m_item.name==item.name)
{
m_item.number += 1;
Debug.Log("物体:" + item.name + ",的数量:" + m_item.number);
return;
}
}
Bag.Mydata.bagData.Add(item);
Debug.Log("加入物体");
}
}
把这个挂到物体身上,参数填好,然后进行测试,复制5个斧头,然后查看数据是否正确添加到背包数据里
测试成功
三、将数据与背包的界面联系起来
,我们创建一个BagGuiManager脚本用来管理GUI界面,我们要做的就是使用这个脚本根据背包数据创建对应的图片。
写一个RefreshItem方法对背包进行刷新(重新根据背包数据生成物体)
CreatGUIItem是根据传入的item对slot进行赋值,(根据背包里的item数据生成GUI的具体实现)
using UnityEngine;
using UnityEngine.UI;
public class BagGuiManager : MonoBehaviour
{
public static BagGuiManager instacne;
private void Awake()
{
if (instacne != null)
{
Destroy(this);
}
instacne = this;
}
[Header("背包")]
public BagManager bag;
public Slot slot;//对应的格子
public GameObject slotGrid;
public Text itemDes;//物品描述
private void OnEnable()
{
RefreshItem();
itemDes.text = "";
}
public void CreatGUIItem(Item item)
{
Slot newItem = Instantiate(slot, slotGrid.transform, false);//为item,实例化一个slot并赋值
newItem.soltItem = item;
newItem.name = item.name;
newItem.number.text = item.number.ToString();
Debug.Log("显示的数量:" + item.number);
//显示图片
GameObject m_Image = Resources.Load(item.spritePath) as GameObject;
newItem.soltImage = m_Image.GetComponent<Image>();
}
public void RefreshItem()//刷新数量,重新生成
{
for (int i = 0; i < instacne.slotGrid.transform.childCount; i++)
{
if (instacne.slotGrid.transform.childCount == 0)
{
Debug.Log("没有物体可销毁");
break;
}
Destroy(instacne.slotGrid.transform.GetChild(i).gameObject);
Debug.LogError("Destory");
}
//foreach (var item in bag.Mydata.bagData)
//{
//
// CreatGUIItem(item);
//}
for (int i = 0; i < bag.Mydata.bagData.Count; i++)
{
Debug.Log("重新生成");
CreatGUIItem(bag.Mydata.bagData[i]);
}
}
}
我们使用for或者foreach遍历背包数据,为每一个item创建slot,将item的数据赋予slot。我们为solt加一个button,点击的时候就将item的描述赋予背包GUI描述的位置(背包下方)
using UnityEngine;
using UnityEngine.UI;
public class Slot : MonoBehaviour
{
public Item soltItem;
public string name;
public Image soltImage;
public Text number;
public void ItemOnClick()
{
Debug.Log("点击solt");
BagGuiManager.instacne.itemDes.text = soltItem.des;
}
}
slot是一个预制体,它是显示在背包中的图片,它拥有数量和图片的属性,创造slot就是创造背包中的ui,
这里的图片赋值使用的是资源加载方式,
一,将做好的图片预制体放在Resources目录,根据路径加载这个预制体,从而获得其图片并赋值。(as 加载方式)
GameObject m_Image = Resources.Load(item.spritePath) as GameObject;
newItem.soltImage.sprite = m_Image.GetComponent<Image>().sprite;
二,通过Resouces.Load泛型加载
(泛型加载方式)
newItem.soltImage.sprite = Resources.Load<Sprite>(item.spritePath);//不能使用as Sprite,
//会失败,要使用泛型的加载
最后我们需要每次添加新物体的时候都对GUI背包进行刷新,即在ItemOnWorld 中碰到物体,添加到数据背包的时候,添加一步刷新GUI界面,并且调用BagManager中的SaveGame方法
成功将背包数据和背包GUI联系起来
最后我们在背包脚本中调用读取方法,在每次游戏开始时,读取Json数据,刷新背包GUI。
四、完整代码参考
using UnityEngine;
using UnityEngine.UI;
public class BagGuiManager : MonoBehaviour
{
public static BagGuiManager instacne;
private void Awake()
{
if (instacne != null)
{
Destroy(this);
}
instacne = this;
}
[Header("背包")]
public BagManager bag;
public Slot slot;
public GameObject slotGrid;
public Text itemDes;
private void OnEnable()
{
RefreshItem();
itemDes.text = "";
}
public void CreatGUIItem(Item item)
{
Slot newItem = Instantiate(slot, slotGrid.transform, false);
//newItem.gameObject.transform.SetParent(slotGrid.transform,false);//设置父物体
newItem.soltItem = item;
newItem.name = item.name;
newItem.number.text = item.number.ToString();
Debug.Log("显示的数量:" + item.number);
//显示图片
//GameObject m_Image = Resources.Load(item.spritePath) as GameObject;
//newItem.soltImage.sprite = m_Image.GetComponent<Image>().sprite;//做成预制体,然后通过加载预制体赋予图片,as 加载方式
newItem.soltImage.sprite = Resources.Load<Sprite>(item.spritePath);//不能使用as Sprite,会失败,要使用泛型的加载
}
public void RefreshItem()//刷新数量,重新生成
{
for (int i = 0; i < instacne.slotGrid.transform.childCount; i++)
{
if (instacne.slotGrid.transform.childCount == 0)
{
Debug.Log("没有物体可销毁");
break;
}
Destroy(instacne.slotGrid.transform.GetChild(i).gameObject);
Debug.LogError("Destory");
}
//foreach (var item in bag.Mydata.bagData)
//{
//
// CreatGUIItem(item);
//}
for (int i = 0; i < bag.Mydata.bagData.Count; i++)
{
Debug.Log("重新生成");
CreatGUIItem(bag.Mydata.bagData[i]);
}
}
}
using UnityEngine;
using UnityEngine.UI;
public class Slot : MonoBehaviour
{
public Item soltItem;
public string name;
public Image soltImage;
public Text number;
public void ItemOnClick()
{
Debug.Log("点击solt");
BagGuiManager.instacne.itemDes.text = soltItem.des;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemOnWorld : MonoBehaviour
{
//[Header("物体所属的背包")]
//public BagManager Bag;
private Item item=new Item();
[Header("物体属性")]
public string name;
public int number;
public string des;
public string type;
public string spritePath;
private void Awake()//将属性赋予物体
{
item.name = name;
item.number = number;
item.des = des;
item.type = type;
item.spritePath = spritePath;
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
{
AddNewItem();
Destroy(this.gameObject);
}
}
private void AddNewItem()
{
foreach (var m_item in BagManager.instacne.Mydata.bagData)//检测有没有同名物体,没有就添加
{
if (m_item.name==item.name)
{
m_item.number += number;
Debug.Log("物体:" + item.name + ",的数量:" + m_item.number);
BagGuiManager.instacne.RefreshItem();
return;
}
}
BagManager.instacne.Mydata.bagData.Add(item);
Debug.Log("加入物体");
BagGuiManager.instacne.RefreshItem();
// BagGuiManager.instacne.CreatGUIItem(item);
}
}