以本地资源类(ScriptableObject)实现数据存储/读取
//背包资源类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Inventory")]
//背包类
public class Inventory : ScriptableObject
{
#region
/public static Inventory GetInventory()
{
return Resources.Load("Mybag");
}
/
#endregion

//物品类列表
public List<Items> itemList = new List<Items>();

}

//物品类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Item" ,menuName = "Inventory/New Item")]
//物品类
public class Items : ScriptableObject
{
public string itemName ;//物品名称
public Sprite ItemImage;//物品图标
public int ItemHild;//物品数量
[TextArea]//文本框,存储多字符串
public string ItemInfo;//物品信息
public bool equip;//可可装备属性
}

//UI预制件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Slot : MonoBehaviour
{
public int slotID;//空格的ID
//public Items slotItem;
public Image slotImage;//物品图标
public Text slotNum;//物品数量
private Button itemButton;//可点击物体按钮
public GameObject itemInSlot;//物品整体UI
public string slotInfo;//物品信息

private void Awake()
{
    itemButton = this.gameObject.GetComponentInChildren<Button>();
    itemButton.onClick.AddListener(ItemOnClecked);
}

public void ItemOnClecked()
{
    InventoryManager.UpdateItemInfo(slotInfo );//点击时显示物品信息,
    //(物品位置交换后UI预制件中仍存储原来物品的信息,调用的也是创建时赋值的信息)场景重新加载 时UI预制件中的信息得到更新
}

public void SetupSlot (Items item)//刷新背包时传过来的本地资源中的物品对象
{
    if(item == null )//本地背包列表中物品为空时吟唱空白的物品对象,然后返回
    {
        itemInSlot.SetActive(false);
        return;
    }
    //不为空时对UI预制件进行赋值
    slotImage.sprite = item.ItemImage;//图标
    slotNum.text = item.ItemHild.ToString();//数量
    slotInfo = item.ItemInfo;//物品信息
}

}

//世界中的物品
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//世界中的物品脚本
public class ItemOnWord : MonoBehaviour
{
public Items thisItem;//物品种类
public Inventory platerInventer;//要加入的背包

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject .CompareTag ("Player"))//Tag相同时返回TRUE,
    {
        AddItems();
    }
    Destroy(this.gameObject);
}

public void AddItems()
{
    if (!platerInventer.itemList.Contains (thisItem ))//List方法包含此元素时返回TRUE,不包含返回FALSE
    {
        for (int i = 0; i < platerInventer.itemList.Count; i++)//背包中没有该物品时遍历
        {
            if (platerInventer .itemList[i]==null) //将物品添加到第一个空位置
            {
                platerInventer.itemList[i] = thisItem;
                break;//跳出循环
            }
        }
    }else
    {
        thisItem.ItemHild += 1;//背包中有该物品时数量加一
    }
    InventoryManager.RefreshItem();//刷新背包
}

}

//背包管理脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//背包管理脚本
public class InventoryManager : MonoBehaviour
{
public static InventoryManager instance;

public Inventory myBag;
public GameObject parentPanle;
//public Slot slotPrefab;
public GameObject prefab;
public Text itemInfromation;

//运行时的物品List,与本地数据保持一致
public List<GameObject> slot = new List<GameObject>();


private void Awake()//单例模式
{
    if (instance != null)
        Destroy(this);
    instance = this;
}

private void OnEnable()//启用时刷新一次
{
    //print("refs");
    //print(parentPanle.transform.childCount);
    RefreshItem();
    instance.itemInfromation.text = " ";
}

public static void UpdateItemInfo(string ItemInfo)
{
    instance.itemInfromation.text = ItemInfo;
}

public static void RefreshItem()
{
    //清空背包
    ClearBag();
    //清空后,再根据本地资源类重新生成UI预制件设置其中的Items相关属性
    for (int i=0;i< instance.myBag.itemList.Count;i++)
    {
        //CreateNewItem(item);
        instance.slot.Add(Instantiate(instance.prefab));
        instance.slot[i].transform.SetParent(instance.parentPanle.transform);
        instance.slot[i].GetComponent<Slot>().slotID = i;
        instance.slot[i].GetComponent<Slot>().SetupSlot(instance.myBag.itemList[i]);

    }
}
//清空UI中背包所有物品的方法
public static void ClearBag()
{
    if (instance.parentPanle.transform.childCount == 0)
        return;
    for (int i = 0; i < instance .parentPanle .transform .childCount ; i++)
    {
        Destroy(instance.parentPanle.transform.GetChild(i).gameObject);
        instance.slot.Clear();
    }
}

}

//------------------------物品拖拽/交换位置-----------------------------------//
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ItemOnnDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler//拖拽接口
{
public Transform originatParent;
public Inventory myBag;
private int currentItemID;

public void OnBeginDrag(PointerEventData eventData)//按下时
{
    originatParent = transform.parent;//记录初始所在父物体
    currentItemID = originatParent.GetComponent<Slot>().slotID;//记录初始父物体在界面/本地数据List中位置
    transform.SetParent(transform.parent.parent);//点击后将物体UI的父物体设置为与抽屉的父物体同级,方便显示
    transform.position = eventData.position;//物体UI位置跟随屏幕滚光标
    GetComponent<CanvasGroup>().blocksRaycasts = false;//隐藏物品图标屏幕射线检测,使射线可检测到下层父级物体
}

public void OnDrag(PointerEventData eventData)//拖拽时
{
    transform.position = eventData.position;//拖拽时物体UI根数屏幕光标
    print(eventData.pointerCurrentRaycast.gameObject.name);//屏幕射线检测到的物体名称
}

public void OnEndDrag(PointerEventData eventData)//拖拽结束时
{
    if (eventData.pointerCurrentRaycast.gameObject != null)//如果屏幕射线检测到的物体不为空时
    {
        if (eventData.pointerCurrentRaycast.gameObject.name == "Item Image")//物品栏有物品时,物品未隐藏可被检测到(物品UI的图标)
        {
            //原物体UI移动到背包中目标物体UI位置
            transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform.parent.parent);//物品UI图标的父级的父级(Slot)
            transform.position = eventData.pointerCurrentRaycast.gameObject.transform.parent.parent.position;
            //将目标物体UI移动到原物体UI位置
            eventData.pointerCurrentRaycast.gameObject.transform.parent.SetParent(originatParent);
            eventData.pointerCurrentRaycast.gameObject.transform.parent.position = originatParent.position;

            //交换本地数据中物体的存储位置
            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;
            //交换存储位置

            GetComponent<CanvasGroup>().blocksRaycasts = true;//交换完成开启屏幕射线检测,可再次拖拽
            return;//目标栏有物体,交换完成退出方法
        }
        if (eventData.pointerCurrentRaycast.gameObject.name == "Slot(Clone)")//目标栏为空时(检测到的是抽屉)
        {
            //原物体之间放入目标抽屉
            transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform);
            transform.position = eventData.pointerCurrentRaycast.gameObject.transform.position;
            //将本地数据中的空物体赋值为,本地数据库中的目标物体
            myBag.itemList[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID] = myBag.itemList[currentItemID];
            //如果如表抽屉不是原来的抽屉时执行
            if (eventData.pointerCurrentRaycast.gameObject.GetComponent<Slot>().slotID != currentItemID)
                myBag.itemList[currentItemID] = null;//之后本地数据中的目标物体设为空

            GetComponent<CanvasGroup>().blocksRaycasts = true;//交换完成开启屏幕射线检测,可再次拖拽
            return;//目标栏有物体,交换完成退出方法
        }
    }
    //其他任何位置返回原位(非UI元素时)
    transform.SetParent(originatParent);
    transform.position = originatParent.position;
    GetComponent<CanvasGroup>().blocksRaycasts = true;
}

}