一、 效果展示
二、 源代码
1,ItemManager.cs
//逻辑简介:该脚本作用是生成背包格子和加载背包物品,获得被拖拽物品和目标物品
//配置:1,需要Scroll View来存放背包物品。
//2,将要作为模板的物品名字更改为EquipSlotTemplate。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ItemManager : MonoBehaviour
{
[SerializeField] private GameObject currentObject;
GameObject EquipSlotTemplate;
public static ItemManager instance;
Transform content;
public GameObject nowItem;
public GameObject toItem;
public List<Item> itemsList = new List<Item>();
//public Dictionary<string, Item> itemsDic = new Dictionary<string, Item>();
public Dictionary<int,GameObject> grid=new Dictionary<int,GameObject>();
AmourTable amourTable;
WeaponTable weaponTable;
private void Awake()
{
amourTable = Resources.Load<AmourTable>("TableData/AmourTable");
weaponTable = Resources.Load<WeaponTable>("TableData/WeaponTable");
AddItem(amourTable.DataList[0]);//添加装备
AddItem(amourTable.DataList[1]);
AddItem(amourTable.DataList[2]);
AddItem(amourTable.DataList[3]);
AddItem(amourTable.DataList[0]);
AddItem(amourTable.DataList[0]);
AddItem(amourTable.DataList[0]);
AddItem(weaponTable.DataList[0]);
content = GameObject.Find("Item_Content").transform;
EquipSlotTemplate = GameObject.Find("EquipSlotTemplate");
if (instance == null)
{
instance = this;
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
int rowCount = 0;
int columnCount = 0;
float xOffset = 173f;
float yOffset = -127f;
//生成格子
for (int i = 0; i < 20; i++)
{
GameObject equipSlot = Instantiate(EquipSlotTemplate);
equipSlot.transform.SetParent(content, false);
RectTransform rectTransform = equipSlot.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(columnCount * xOffset-180f, rowCount * yOffset+82f);
columnCount++;
if (columnCount >= 3)
{
columnCount = 0;
rowCount++;
}
if (equipSlot.GetComponent<BaseItem>() == null)
{
equipSlot.AddComponent<BaseItem>();
}
grid.Add(i, equipSlot);
}
UpdateItem();
}
private void AddItem(Item item)
{
itemsList.Add(item);
}
int index = 0;
public void UpdateItem()
{
//遍历背包物品字典,将背包物品以此赋给格子。
foreach (var item in itemsList)
{
grid[index].GetComponent<Image>().sprite = item.sprite;
grid[index].GetComponent<BaseItem>().item = item;
index++;
if (index >= grid.Count)
{
break;
}
}
}
}
2,BaseItem.cs
//逻辑简介:拖拽物品时,记录被拖拽物品的初始父物体,被拖拽物品先作为canvas的子物体,拖拽成功后,让被拖拽物品的父物体为目标物体的父物体,目标物体的父物体成为被拖拽物品的的父物体。然后再交换位置。
//配置:1,把Canvas的名称改为StaticCanvas,若不更改的话,需要修改代码canvas = GameObject.Find("StaticCanvas").GetComponent<Canvas>();
//2,所有装备槽有一个父物体。名字为“EquipSlots”。每个装备槽根据类型也要改名为“Head_Slot”等等。背包槽的父物体也要改名为“Item_Content”。
//3,该脚本通过ItemManager挂载到每个物品上。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class BaseItem :MonoBehaviour,IPointerEnterHandler, IPointerExitHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
{
[SerializeField] private GameObject currentObject;
RectTransform rectTransform;
Canvas canvas;
Transform canvasTranform; // 作为临时父级容器,用于装载和移除拖动的图像
Transform currentParentTrans;
[SerializeField] Transform itemParentTrans; // 作为临时父级容器,用于装载和移除拖动的图像
Image image;
public bool hasEquipSlot;
Vector2 currentRectTrans;
[SerializeField] public Item item;
private void Awake() {
canvas = GameObject.Find("StaticCanvas").GetComponent<Canvas>();
canvasTranform = GameObject.Find("StaticCanvas").transform;
rectTransform = GetComponent<RectTransform>();
image = GetComponent<Image>();
if (item == null)
{
item = new Item();
}
}
private void Start() {
if (transform.name == "Head_Slot")//给装备槽 加type
{
item.type = "头盔";
}
else if (transform.name == "Clothe_Slot")
{
item.type = "衣服";
}
else if (transform.name == "Wrist_Slot")
{
item.type = "手腕";
}
else if (transform.name == "Shoes_Slot")
{
item.type = "鞋子";
}
else if (transform.name == "Horse_Slot")
{
item.type = "马匹";
}
else if (transform.name == "Wepon_Slot")
{
item.type = "武器";
}
currentParentTrans = transform.parent;
}
public void OnPointerEnter(PointerEventData eventData)
{
currentObject = eventData.pointerEnter;
ItemManager.instance.toItem = gameObject;
}
public void OnPointerExit(PointerEventData eventData)
{
ItemManager.instance.toItem = null;
}
public void OnBeginDrag(PointerEventData eventData)
{
if (item.name == null)
{
return;
}
currentRectTrans = rectTransform.anchoredPosition;
currentParentTrans = transform.parent;
ItemManager.instance.nowItem = gameObject;
ItemManager.instance.toItem = null;
itemParentTrans = currentObject.transform.parent; //记录当前物体的父物体位置
currentObject.transform.SetParent(canvasTranform); //将当前物体移动到临时父级容器
}
public void OnDrag(PointerEventData eventData)
{
if (item.name == null)
{
return;
}
transform.GetComponent<Button>().interactable = false;
image.raycastTarget = false;
// 根据鼠标的移动来调整物体的位置
rectTransform.anchoredPosition += eventData.delta / canvas.scaleFactor;
}
public void OnEndDrag(PointerEventData eventData)
{
if (item.name == null)
{
return;
}
Debug.Log(item.sprite);
if (ItemManager.instance.toItem == null) //物品栏装备没有拖动到 装备栏和物品栏 即toItem为null
{
currentObject.transform.SetParent(itemParentTrans);
// 将当前物体的位置重置为原始位置
rectTransform.anchoredPosition = currentRectTrans;
}
else if (ItemManager.instance.toItem.transform.parent.name == "EquipSlots"&¤tParentTrans.name=="Item_Content") //物品栏装备拖动到到了装备槽上
{
//type判断
if (ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type)
{
//父类交换
ItemManager.instance.nowItem.transform.SetParent(ItemManager.instance.toItem.transform.parent, false);//把这个物体作为装备槽父物体的子物体。
ItemManager.instance.toItem.transform.SetParent(currentParentTrans, false);
//位置交换
Vector2 temp = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;//获得装备槽本地坐标
ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = currentRectTrans;
ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = temp;//把装备槽本地坐标赋值给该物体。
}
else
{
currentObject.transform.SetParent(itemParentTrans);
rectTransform.anchoredPosition = currentRectTrans;
}
}
else if (currentParentTrans.name=="EquipSlots"&&ItemManager.instance.toItem.transform.parent.name=="Item_Content")//装备栏移动到物品栏
{
//判断type是否相同 相同交换位置 或者 不同(装备和格子)也交换位置。
if ((ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type) || ItemManager.instance.toItem.GetComponent<BaseItem>().item.name == null)
{
//父类交换
ItemManager.instance.nowItem.transform.SetParent(ItemManager.instance.toItem.transform.parent, false);
ItemManager.instance.toItem.transform.SetParent(currentParentTrans, false);
//位置交换
Vector2 temp = currentRectTrans;
ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;
ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;
ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type = ItemManager.instance.toItem.GetComponent<BaseItem>().item.type;
}
else
{
currentObject.transform.SetParent(itemParentTrans);
rectTransform.anchoredPosition = currentRectTrans;
}
}
//物品栏物品相互更换位置
else if (ItemManager.instance.toItem.transform.parent.name == "Item_Content" && currentParentTrans.name == "Item_Content")//
{
//父类交换
ItemManager.instance.toItem.transform.SetParent(currentParentTrans);
ItemManager.instance.nowItem.transform.SetParent(currentParentTrans);
//位置交换
Vector2 temp = currentRectTrans;
ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;
ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;
}
//装备栏之间交换位置
else if (ItemManager.instance.toItem.transform.parent.name == "EquipSlots" && currentParentTrans.name == "EquipSlots")
{
if (ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type)
{
//父类交换
ItemManager.instance.toItem.transform.SetParent(currentParentTrans);
ItemManager.instance.nowItem.transform.SetParent(currentParentTrans);
//位置交换
Vector2 temp = currentRectTrans;//获得nowItem本地坐标
ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;
ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;
}
else
{
currentObject.transform.SetParent(itemParentTrans);
rectTransform.anchoredPosition = currentRectTrans;
}
}
// 恢复鼠标点击
transform.GetComponent<Button>().interactable = true;
image.raycastTarget = true;
ItemManager.instance.nowItem = null;
ItemManager.instance.toItem = null;
}
}
public class Item
{
public int id;
public string name;
public Sprite sprite;
public int price;
public string type;
}
3,加载资源
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Data/AmourTable", fileName = "AmourTable")]
public class AmourTable : ScriptableObject
{
public List<AmourTableItem> DataList = new List<AmourTableItem>();
public Dictionary<string, AmourTableItem> WeaponDataList = new Dictionary<string, AmourTableItem>();
}
[System.Serializable]
public class AmourTableItem:Item
{
public int weight;
public int defense;
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(menuName = "Data/ItemTable", fileName = "ItemTable")]
public class ItemTable : ScriptableObject
{
public List<ItemTableItem> DataList = new List<ItemTableItem>();
public Dictionary<string, ItemTableItem> ItemDataList = new Dictionary<string, ItemTableItem>();
}
[System.Serializable]
public class ItemTableItem:Item
{
public int Price;
public int weight;
}